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

时间:2016-04-28 07:36:20

标签: .net multithreading invoke

我正在开发一个小型软件,用于从设备检索数据并将其发送到服务器。因为它是一个桌面软件所以我必须将当前可用的消息添加到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);
        }
    }

1 个答案:

答案 0 :(得分:0)

解决了这个问题:)

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

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

中查看更多内容