繁体   English   中英

C# 向存储过程调用添加额外/不需要的参数

[英]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;

![文字](E://pulltab/capture.png)

前 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM