如何使用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()
看到更多
我正在开发一个用于从设备检索数据并将其发送到 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()
看到更多