异步任务不会产生良好的响应

时间:2017-02-14 13:09:02

标签: c# .net web-services asynchronous task

我试图等待功能结束来执行某项任务。 HEre是我的架构

  • Windows服务的课程
  • 用于与设备通信的类,实例为" ilon"。这个类可以访问另一个允许我使用webservice的类

从Windows服务中,我正在这样做:

Item_DataColl resultSet = ilon.read("Net/LON/10/LampDali1/nviRunHours");

以下是" ilon"的读取功能的定义。类:

internal Item_DataColl read(string UCPTName)
{
       return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours").Result;
}

Ilonbind变量与允许我与webservice建立连接的类相关联。所以他得到了一个名为" invoke_command_read"的函数,定义为:

public async Task<Item_DataColl> invoke_command_READ(string UCPTName)
{
    return await Task.Run(() => thread_command_READ_result(UCPTName));
}

在同一个班级,我终于有了这个功能:

private Item_DataColl thread_command_READ_result(string UCPTName)
{
    Item_DataColl resultSet = null;
    if (UCPTName != null)
    {
        try
        {
            OnProgressBarUpdate(progressBar.UnknownEnd);
            resultSet = connector.command_READ(UCPTName);
            readOperationDone(resultSet);
            OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);

        }
        catch (Exception e)
        {
            OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
        }
        finally
        {
            OnProgressBarUpdate(progressBar.Invisible);
        }
    }
    return resultSet;
}

指令&#34; resultSet = connector.command_READ(UCPTName)&#34;工作得很好,直到webservice请求的结果才会返回结果。但我无法获得任何网络服务的结果。

我的任务使用得好吗?

1 个答案:

答案 0 :(得分:1)

  

我的任务使用得好吗?

没有

这是&#39>正在进行的事情:

  1. 实际操作是网络通话,因此非常适合async
  2. 但代理为您提供了同步API,因此您可以阻止线程。 (不好)
  3. 因此invoke_command_READ将同步API包装在Task.Run中,因此它会阻塞线程池线程。 (不好)
  4. 然后read使用Result阻止该任务,每个请求阻止两个线程并causing a deadlock。 (真的很糟糕)
  5. 您的代码是同步异步同步,这对于同时使用两个反模式(sync-over-asyncasync-over-sync)非常重要。

    要解决此问题,请始终保持异步,或者一直同步。始终异步更高效,但需要在代理上使用异步API:

    public async Task<Item_DataColl> invoke_command_READ(string UCPTName)
    {
      Item_DataColl resultSet = null;
      if (UCPTName != null)
      {
        try
        {
          OnProgressBarUpdate(progressBar.UnknownEnd);
          resultSet = await connector.command_READAsync(UCPTName);
          readOperationDone(resultSet);
          OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);
        }
        catch (Exception e)
        {
          OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
        }
        finally
        {
          OnProgressBarUpdate(progressBar.Invisible);
        }
      }
      return resultSet;
    }
    
    internal Task<Item_DataColl> readAsync(string UCPTName)
    {
      return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours");
    }
    

    所有方式同步可能会更容易,因为您的代理是同步的,并且您的消费代码是同步的:

    internal Item_DataColl read(string UCPTName)
    {
      return ilonBind.invoke_command_READ("Net/LON/10/LampDali1/nviRunHours");
    }
    
    public Item_DataColl invoke_command_READ(string UCPTName)
    {
      return thread_command_READ_result(UCPTName);
    }