外部函数调用块 UI 线程
External Function Call Blocks UI thread
我正在开发一个通过以太网与运动控制器通信的应用程序。
为了连接到控制器,我使用了供应商提供的库,连接你创建一个控制器的实例然后告诉它连接,这有机会阻塞几秒钟(没有可控的超时) 如果没有控制器存在。这导致 UI.
冻结
为了避免这种情况,我想我可以使用任务 运行 不同线程中的连接。
ConnectionTask = Task.Factory.StartNew(() =>
{
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
RMC.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}
}, TaskCreationOptions.LongRunning);
这没有任何效果,UI 仍然锁定。
我认为我正在正确使用它们,就好像我用下面的代码替换它一样 UI 很好,即使单独的线程在消息出现之前需要几秒钟。
ConnectionTask = Task.Factory.StartNew(() =>
{
int x = 1;
while (x != 0) x++;
this.logger.Log("Failed to connect");
}, TaskCreationOptions.LongRunning);
有什么方法可以识别正在发生的事情并防止我对其内部工作一无所知的调用锁定 UI 线程。
使用 async
/await
,类似于:
public async void MyButton_Click(object sender, EventArgs e)
{
await CreateEthernetLink();
this.logger.Log("Connected!");
}
private async Task CreateEthernetLink()
{
var task = Task.Run(() => {
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
rmc.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}});
await task;
}
await
将捕获当前线程(或 SynchronizationContext
- 在本例中是被阻塞的 UI 线程)并在异步工作完成后恢复它。
所以线程都是在幕后为您处理的,您应该注意到您的应用程序没有任何区别,除了您的应用程序在执行连接时不再冻结。
编辑: 我还在你的代码中注意到你正在初始化 rmc 但在 RMC[=26= 上调用连接].我认为这是不正确的。
我正在开发一个通过以太网与运动控制器通信的应用程序。
为了连接到控制器,我使用了供应商提供的库,连接你创建一个控制器的实例然后告诉它连接,这有机会阻塞几秒钟(没有可控的超时) 如果没有控制器存在。这导致 UI.
冻结为了避免这种情况,我想我可以使用任务 运行 不同线程中的连接。
ConnectionTask = Task.Factory.StartNew(() =>
{
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
RMC.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}
}, TaskCreationOptions.LongRunning);
这没有任何效果,UI 仍然锁定。
我认为我正在正确使用它们,就好像我用下面的代码替换它一样 UI 很好,即使单独的线程在消息出现之前需要几秒钟。
ConnectionTask = Task.Factory.StartNew(() =>
{
int x = 1;
while (x != 0) x++;
this.logger.Log("Failed to connect");
}, TaskCreationOptions.LongRunning);
有什么方法可以识别正在发生的事情并防止我对其内部工作一无所知的调用锁定 UI 线程。
使用 async
/await
,类似于:
public async void MyButton_Click(object sender, EventArgs e)
{
await CreateEthernetLink();
this.logger.Log("Connected!");
}
private async Task CreateEthernetLink()
{
var task = Task.Run(() => {
try
{
RMCLink rmc = RMCLink.CreateEthernetLink(DeviceType.RMC70, "192.168.0.55");
rmc.Connect();
}
catch
{
this.logger.Log("Failed to connect");
}});
await task;
}
await
将捕获当前线程(或 SynchronizationContext
- 在本例中是被阻塞的 UI 线程)并在异步工作完成后恢复它。
所以线程都是在幕后为您处理的,您应该注意到您的应用程序没有任何区别,除了您的应用程序在执行连接时不再冻结。
编辑: 我还在你的代码中注意到你正在初始化 rmc 但在 RMC[=26= 上调用连接].我认为这是不正确的。