如何使用Invoke避免跨线程操作?

How to use Invoke for avoiding Cross Thread operation?

我正在开发一个用于从设备检索数据并将其发送到 server.As 的小软件,它是一个桌面软件,所以我必须将当前可用的消息添加到 GUI.It 才能正常工作,直到我加入那些线程。当我尝试通过将标志(当前 IsRunning 是我的标志)值设置为 false 来停止此线程,然后尝试向 Gui 添加一条消息时,它冻结了整个 application.probably 死锁问题,但我对此并不完全确定。 请帮助

线程停止点

try
        {
            IsRunning = false;
           _bgThread.Join(); //this makes a deadlock probably

           //_bgThread.Join(7000); //this works fine 
        }
        catch (ThreadStartException ese)
        {
            throw ese;
        }

//线程方法

private void DeviceSync()
    {
        while (IsRunning)
        {
            // ...statement
        }
    //now what actually happen in my case is 
    //when i try to stop the thread by setting the value of "IsRunning" false
    //it comes to this line and pass a message to UI by throwing OnThrowingMessage event

        var info = "Service Stopped at: " + DateTime.Now.ToString(BusinessRules.DateTimeFormat);
        OnThrowingMessage(info, MessageType.Important);// this event fails to bind message to UI thread causes freeze UI
    }

//委托方法

 private void OnGuiMessaging(string message, MessageType messageType)
    {
        try
        {
    //for avoiding Invalid Cross-thread Operations as sometimes it is calling from background thread
            if (this.currentStatedataGridView.InvokeRequired)
            {
                Console.WriteLine("Here it is for the first time ");
               //Application freeze here 
                this.currentStatedataGridView.Invoke(new SomeDelgate(OnGuiMessaging), new object[] { message, messageType });
            }
            else
            {
               //add row
                string[] rowData = new string[] { DateTime.Now.ToString(BusinessRules.DateTimeFormat), message };
                currentStatedataGridView.Rows.Insert(0, rowData);
                currentStatedataGridView.Rows[0].DefaultCellStyle.BackColor = rowColor;
             }
       }
        catch (Exception ex)
        {
            Log.Error(ex);
        }
    }

解决了这个问题:)

用 Delegate.BeginInvoke 替换 Delegate.Invoke 解决了我的问题,因为它在 UI 线程上执行时异步执行,并且调用线程不等待完成。另一方面 Control.Invoke 在 UI 线程上执行,但调用线程在继续之前等待完成。

可以从What's the difference between Invoke() and BeginInvoke()

看到更多