C# 外部函数调用阻止UI线程

C# 外部函数调用阻止UI线程,c#,multithreading,.net-4.0,task,C#,Multithreading,.net 4.0,Task,我正在开发一个通过以太网与运动控制器对话的应用程序 要连接到控制器,我使用供应商提供的库,要连接,请创建控制器的实例,然后告诉它连接,如果没有控制器,这有可能阻塞几秒钟(没有可控超时)。这会导致UI冻结 为了避免这种情况,我想我可以使用任务在不同的线程中运行连接 ConnectionTask = Task.Factory.StartNew(() => { try { RMCLink rmc = RMCLink.CreateEthernetLink(Devic

我正在开发一个通过以太网与运动控制器对话的应用程序

要连接到控制器,我使用供应商提供的库,要连接,请创建控制器的实例,然后告诉它连接,如果没有控制器,这有可能阻塞几秒钟(没有可控超时)。这会导致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线程。

使用
异步
/
等待
,大致如下:

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;
 }
wait
将捕获当前线程(或
SynchronizationContext
——在本例中是被阻止的UI线程),并在异步工作完成后将其还原

因此,线程都是在后台为您处理的,您应该注意到应用程序中没有什么不同,只是在执行连接时应用程序不再冻结


编辑:我还注意到,在您的代码中,您正在初始化rmc,但在rmc上调用connect。我不认为这是正确的。

尽管答案很好,但请考虑将解释与代码一起发布。谢谢这实际上会在调用方的单独线程上执行RMCLink.CreateEthernetLink调用吗?@MickyDuncan我已经添加了一些解释。谢谢。由于CreateEthernetLink内部不执行任何等待,因此此代码将无法工作。因此,它不能被标记为异步。它现在将编译,但将同步运行,因为它内部没有任何等待。因此,它有原始的问题。