所以,我有一个叫方法的胜利形式
dvm.SetVoltage(excitationVoltage, rigNo);
在另一个类中运行任务
public void SetVoltage(double voltage, int rigNum)
{
Task.Run(() => ReadDVMWorker());
}
工作人员完成操作(设置电压)后,将在主Form1.cs中触发一个事件
private void dvmVoltageSet(object sender, VoltageEventArgs e)
{
VoltageSet = e.VolSet;
TestLvdtNull();
}
调用TestLvdtNull方法:
private void TestLvdtNull()
{
tbMessage.Location = new Point((int)(x / 2 - 250), 150);
}
一旦到达tbMessage行,由于它启动了另一个线程而不是在其中创建的tbMessage,它会引发异常,如何防止它启动新线程并继续使用Main线程?
我查看了单线程同步上下文,但是无法对其进行编译,我知道您可以调用:
tbMessage.Invoke((Action)delegate
{
tbMessage.Location = new Point((int)(x / 2 - 250), 150);
});
但是我有许多控件,它们的许多属性都在变化,必须有一种方法将UI保留在主线程上吗?
答案 0 :(得分:1)
所有UI控件都在一个线程中创建。这是设计使然的许多UI框架。完成任务后,您必须返回UI线程以访问UI控件。
注释中提到的一个选项是使用 async / await ,其中await
关键字之后的方法的一部分与async方法之前的相同的线程上执行。
// UI thread
await ReadDVMWorker(); // executed at ThreadPool
// UI thread
如果您希望继续使用 Task ,则可以将ContinueWith
方法与正确的TaskScheduler
参数一起使用,以确保您返回到UI线程。例如。 TaskScheduler.FromCurrentSynchronizationContext()
异步/等待尝试代码:
private async void button1_Click(object sender, EventArgs e)
{
// Call the method that runs asynchronously.
string result = await WaitAsynchronouslyAsync();
// Display the result.
textBox1.Text += result;
}
//The following method runs asynchronously.The UI thread is not
//blocked during the delay.You can move or resize the Form1 window
//while Task.Delay is running.
public async Task<string> WaitAsynchronouslyAsync()
{
await dvm.SetVoltage(5, rigNo); //Task.Delay(10000);
return "Finished";
}
答案 1 :(得分:0)
您可以使用一种方法来更新任意控件
private void dvmVoltageSet(object sender, VoltageEventArgs e)
{
VoltageSet = e.VolSet;
TestLvdtNull(tbMessage);
TestLvdtNull(tbMessage2);
}
private void TestLvdtNull(Control control)
{
control.BeginInvoke((MethodInvoker)delegate()
{
control.Location += new Point((int)(x / 2 - 250), 150);
});
}
答案 2 :(得分:0)
尝试了几种不同的方法来解决问题后,我使用SynchronizationContext解决了问题。
这将获取线程的SyncronizationContext:
private SynchronizationContext _synchronizationContext;
SynchronizationContext uiContext = SynchronizationContext.Current;
然后在另一个类中运行我的任务之后,以前在该类中我遇到了跨线程调用异常,然后调用要使用相同UI线程的方法:
uiContext.Post(MethodToCallOnTheSameUIThread, "string");
此后,我可以修改和更新我的文本框和其他控件!
您可以通过以下方式检查线程ID:
int id = Thread.CurrentThread.ManagedThreadId;
Console.WriteLine("Thread: " + id);
感谢Mike Peretz and his CodeProject