c# - 将 windows.forms 控件保留在同一个主线程中
问题描述
所以,我有一个调用方法的获胜表格
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,我该如何防止它启动一个新线程并继续使用主线程?
我查看了 singlethreadsynchronizationcontext,但无法编译,我知道您可以调用:
tbMessage.Invoke((Action)delegate
{
tbMessage.Location = new Point((int)(x / 2 - 250), 150);
});
但是我有很多属性变化的控件,必须有一种方法可以将 UI 保持在主线程上吗?
解决方案
所有 UI 控件都在一个线程中创建。这是许多 UI 框架的设计。完成任务后,您必须返回 UI 线程以访问 UI 控件。
注释中提到的一种选择是使用async/await,其中关键字 after 的部分方法在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";
}
推荐阅读
- visual-studio - 如何防止VS中的Output窗口消失?
- node.js - 如何使用 bot builder sdk for node.js 在打字栏中添加“开始”按钮
- angular - 如何订阅已经在 Angular5 中订阅的函数
- powershell - Powershell 比较数组并获取唯一值
- api - 如何使组件项自动与其父项一起更改所有者?
- facebook-graph-api - Facebook Graph API 获取 page_impressions
- java - 检索应用程序的图标不适用于所有应用程序
- javascript - 隐藏输入时 input.select() 不起作用
- c# - SelectSingleNode 中的 StackOverflow
- docker - docker-compose 无法通过服务名称连接到相邻服务