【问题标题】:Wrap a synchronous function in Asynchronous call c#在异步调用c#中包装一个同步函数
【发布时间】:2017-02-16 19:31:59
【问题描述】:

我有一个服务器,它必须通过网络轮询一个设备,以获取信息,处理它,然后将它发送给用户。 设备勘测成为同步阻塞功能。

我的问题是:

如何创建一个自己的异步函数版本来使用Task或其他异步模式来执行这个函数???

考虑以下代码从设备获取信息:

IEnumerable<Logs> GetDataFromEquipment(string ipAddress)
        {
            Equipment equipment = new Equipment();
            //Open communication with equipment. Blocking code.
            int handler = equipment.OpenCommunication(ipAddress);
            //get data from equipment. Blocking code.
            IEnumerable<Logs> logs = equipment.GetLogs(handler);
            //close communication with equipment
            equipment.CloseCommunication(handler);

            return logs;
        }

谢谢

【问题讨论】:

  • 你先让GetLogs异步。
  • 我该怎么做...
  • 你必须让你的 IO 方法异步。例如发布 OpenCommunication 方法。我将首先向您展示如何做到这一点。你的通信是用什么实现的?什么 .net 设施/类?
  • 如果您无权更改Equipment 类的代码,那么您唯一的方法就是在另一个线程上运行该方法-Task.Run 可以很简单。如果您有权访问 Equipment 类 - 为 Open..GetLogsClose.. 添加异步方法。所有 IO 操作都可以并且应该使用 async-await 方法完成,这将避免您浪费应用程序的线程资源只等待响应
  • 设备类是设备制造商外部库的一部分。我用它们与设备通信。如何将这些同步调用转换为异步 IO 方法?

标签: c# asynchronous async-await task


【解决方案1】:

你可以使用异步/等待

 public async Task<IEnumerable<Logs>> GetDataFromEquipment(string ipAddress)
    {

        var task = Task.Run(() =>
        {
            Equipment equipment = new Equipment();
            //Open communication with equipment. Blocking code.
            int handler = equipment.OpenCommunication(ipAddress);
            //get data from equipment. Blocking code.
            IEnumerable<Logs> logs = equipment.GetLogs(handler);
            //close communication with equipment
            equipment.CloseCommunication(handler);

            return logs;
        });

        return await task;
    }

【讨论】:

  • Task.Run() 在一个ThreadPool中创建一个线程,而且代码是阻塞的,这种情况下使用Task.Run正确吗???
  • 调用设备.GetLogs(handler);延迟几秒钟做出反应。 Blocking the ThreadPool中的线程,我看过It's a bad practice...
  • 拨打equipment.GetLogs(handler);延迟几秒回复。 Blocking the ThreadPool中的线程,我看过It's a bad practice...
  • @J.Doe2017 - 与其说是“阻塞”线程,不如说是简单地使用它,特别是避免阻塞你认为更重要的线程;例如也许是 UI 线程。如果您无权将 Equipment 更改为异步,这是唯一的方法。嗯...当然还有很多其他方法,但是如果不重写 Equipment 以正确支持 async-await 样式的异步,您将无法实现适当的线程备用、异步等待情况。
  • .NET 不会为您提供数百个线程供您使用,当然也不会在其默认配置中使用。您最终会得到线程池的大量任务排队,但任何时候只有几个线程在处理它。即便如此,线程池忙于处理这个比您的 UI 线程(或您需要响应更快的其他线程)更好。
最近更新 更多