[英]C# adding extra/unwanted parameters to stored procedure call
我有一个奇怪的问题正在发生。 在我的开发系统上一切正常,但在生产系统上运行代码会添加额外的参数。 这是代码。
public string Read(Setting SettingID, string SettingValue, int GameID)
{
SqlCommand sqlText;
string SettingName = SettingsNames[(int)SettingID];
using (SqlConnection cn = new SqlConnection(DataHandlers.ConnString))
{
sqlText = cn.CreateCommand();
sqlText.CommandType = CommandType.StoredProcedure;
sqlText.CommandText = "Proc_Settings";
sqlText.Parameters.Clear();
sqlText.Parameters.Add(new SqlParameter("SettingName", SettingName));
sqlText.Parameters.Add(new SqlParameter("SettingValue", SettingValue));
sqlText.Parameters.Add(new SqlParameter("Dir", Direction.Read));
sqlText.Parameters.Add(new SqlParameter("GameID", GameID));
sqlText.Parameters.Add("@Return", SqlDbType.Int).Direction = ParameterDirection.ReturnValue;
前 2 个参数添加得很好。 在第三个参数上添加 'DIR' 和 @Return 但 @Return 是一个输入。 第 4 个参数也会发生同样的情况,然后添加第 5 个参数作为返回值。 问题发生时,正在从另一个线程调用该函数。 该线程是一个 com 端口处理程序。 如果我禁用 bios 中的 com 端口,它工作正常,这是有道理的,因为我的开发计算机没有相同数量的端口,因此缺少设备的端口。 一旦我启用端口并且例程启动,轮询线程就是问题开始的时候。 我查看了 VS 中的不同线程,唯一让我了解与该问题相关的代码的是我正在调试的当前线程。 我是否在这里造成线程违规?
这是轮询例程
private void Poll()
{
Actions.init(buffer, length, ComDll, Port); //Function to Initialize
while (Active)
{
// Process the com port
// Currently doesn't get here
}
}
这是 init 函数,
public static void init(byte[] buffer, int length, ID003CommandCreater ComDll, SerialPort Port)
{
byte enable1 = 0;
byte enable2 = 0;
byte[] status = new byte[255]; //Buffer to read data from the serial port
bool initializing = true;
while (initializing)
{
try
{
// Initializes the device
ComDll.Reset(buffer);
length = (int)buffer[1];
Port.Write(buffer, 0, length);
System.Threading.Thread.Sleep(3000);
Port.Read(status, 0, 255); //Fails when device not connected
… More init commands sent
initializing = false;
}
catch
{
if (Port.PortName != settings.Read(Settings.Setting.ComPort, Port.PortName, 0))
{
Port.Close();
initializing = false;
}
//JCM.BVstatus = "Com Failure";
//JCM.bvComFailure = true;
}
}
}
这是错误。
"System.Data.SqlClient.SqlException (0x80131904):过程或函数 Proc_Settings 指定的参数过多。\\n过程或函数 Proc_Settings 指定的参数过多。\\r\\n 在 System.Data.SqlClient.SqlConnection.OnError (System. Data.SqlClient.SqlException 异常,System.Boolean breakConnection,System.Action 1[T] wrapCloseInAction) [0x0004c] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlConnection.OnError(System.Data.SqlClient.SqlException,bool,System.Action
1<System.Action>)\\r\\n 在 System.Data.SqlClient.SqlInternalConnection.OnError(System.Data.SqlClient.SqlException 异常,系统.Boolean breakConnection, System.Action 1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource
1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource
1[T] wrapCloseInAction) [0x00013] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning (System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean callerHasConnectionLock, System.Boolean asyncClose) [0x00152] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.TdsParser.TryRun (System.Data.SqlClient.RunBehavior runBehavior, System.Data.SqlClient.SqlCommand cmdHandler, System.Data.SqlClient.SqlDataReader dataStream, System.Data.SqlClient.BulkCopySimpleResultSet bulkCopyHandler, System.Data.SqlClient.TdsParserStateObject stateObj, System.Boolean& dataReady) [0x009b9] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.TryConsumeMetaData () [0x00040] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlDataReader.get_MetaData () [0x00031] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlDataReader.get_MetaData()\\r\\n at System.Data.SqlClient.SqlCommand.FinishExecuteReader (System.Data.SqlClient.SqlDataReader ds, System.Data.SqlClient.RunBehavior runBehavior, System.String resetOptionsString) [0x000d3] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Boolean async, System.Int32 timeout, System.Threading.Tasks.Task& task, System.Boolean asyncWrite, System.Data.SqlClient.SqlDataReader ds) [0x004d8] in <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n at System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.Threading.Tasks.TaskCompletionSource
1[TResult] 完成、System.Int32 超时、System.Threading.Tasks.Task& 任务、System.Boolean asyncWrite、System.String 方法)[0x00079] 在 <290425a50ff84a639f8c060e2d6>453 r\\n 在 System.Data.SqlClient.SqlCommand.RunExecuteReader (System.Data.CommandBehavior cmdBehavior, System.Data.SqlClient.RunBehavior runBehavior, System.Boolean returnStream, System.String 方法) [0x0000b] 在 <290425a50ff84a639f8c060e2d4530f6>:0 r\\n 在 Sys tem.Data.SqlClient.SqlCommand.ExecuteReader (System.Data.CommandBehavior 行为) [0x0003c] 在 <290425a50ff84a639f8c060e2d4530f6>:0 \\r\\n 在 System.Data.SqlClient.SqlCommand.ExecuteReader () [0x00009040400e] 在 <290425a50ff84a639f8c060e2d4530f6>:0 0 \\r\\n at (wrapper remoting-invoke-with-check) System.Data.SqlClient.SqlCommand.ExecuteReader()\\r\\n at Settings.Read (Settings+Setting SettingID, System.String SettingValue, System.Int32 GameID ) [0x000cb] 在 E:\\Unity\\xxxx\\Assets\\xxxx\\Scripts\\Database\\Settings.cs:192 \\r\\nClientConnectionId:42a5adfe-d934-496e-b678-456fde7d2622\\r\\n错误编号:8144,State:2 ,等级:16"
我之前使用过一些线程,但可能会误解其中的一些。 在这种情况下,Init 必须在轮询线程继续之前成功完成。 初始化完成后,线程将进入一个循环来处理 com 端口。 如果我不等待硬件,那么循环将尝试从 com 端口发送更多数据,这会破坏配置。 为了成功初始化硬件,我必须按顺序执行大约 6 个步骤。 第一个命令会重置设备,在我可以继续与它交谈之前,它只需要 3 秒钟就可以初始化。 我希望线程继续吗? 这个线程只运行设备的代码,没有别的。 所有其他代码继续。 Read 例程是从多个线程调用的。 它在整个程序中使用。
当你使用System.Threading.Thread.Sleep(3000);
您阻塞当前线程作为等待任务完成的一种方式,这可能导致死锁和阻塞的上下文线程
当您等待一定的时间时,您应该使用await System.Threading.Tasks.Task.Delay(3000);
. 因为这个命令不会阻塞当前线程。
要使用此命令,您需要使您的方法异步。
您的代码异步:
public static async System.Threading.Tasks.Task InitAsync(
byte[] buffer,
int length,
ID003CommandCreater ComDll,
SerialPort Port)
{
byte enable1 = 0;
byte enable2 = 0;
byte[] status = new byte[255]; //Buffer to read data from the serial port
bool initializing = true;
while (initializing) {
try {
// Initializes the device
ComDll.Reset(buffer);
length = (int)buffer[1];
Port.Write(buffer, 0, length);
// Doesn't block thread anymore, because we wait until the task is finished.
await System.Threading.Tasks.Task.Delay(300);
Port.Read(status, 0, 255);
… More init commands sent
initializing = false;
}
catch {
if (Port.PortName != settings.Read(Settings.Setting.ComPort, Port.PortName, 0)) {
Port.Close();
initializing = false;
}
//JCM.BVstatus = "Com Failure";
//JCM.bvComFailure = true;
}
}
}
我建议您也创建异步调用此方法的方法,但如果这是不可能的,那么您需要确保没有死锁,并且可以通过一个小的解决方法来实现。
要在同步方法中调用异步方法,我们首先需要添加一个清除线程的类,这样我们就不会阻塞它
NoSynchronizationContextScope 类:
public static class NoSynchronizationContextScope {
public static Disposable Enter() {
var context = SynchronizationContext.Current;
SynchronizationContext.SetSynchronizationContext(null);
return new Disposable(context);
}
public struct Disposable : IDisposable {
private readonly SynchronizationContext _synchronizationContext;
public Disposable(SynchronizationContext synchronizationContext) {
_synchronizationContext = synchronizationContext;
}
public void Dispose() =>
SynchronizationContext.SetSynchronizationContext(_synchronizationContext);
}
}
现在,如果我们使用这些代码行,我们可以在代码中的任何地方调用异步方法。
在同步方法中调用异步方法:
private void MySynchronousMethodLikeDisposeForExample() {
using (NoSynchronizationContextScope.Enter()) {
InitAsync().Wait();
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.