【问题标题】:how to implement async method using Task Parallel Library for I/O operations如何使用任务并行库为 I/O 操作实现异步方法
【发布时间】:2013-08-05 00:50:05
【问题描述】:

我发现对于昂贵的 IO 绑定操作,我可以使用 TaskCompletionSource

如这里所示http://msdn.microsoft.com/en-us/library/hh873177.aspx#workloads

但显示的示例只是等待一段时间并返回 DateTime。

public static Task<DateTimeOffset> Delay(int millisecondsTimeout)
{
 TaskCompletionSource<DateTimeOffset> tcs = null;
 Timer timer = null;

 timer = new Timer(delegate
 {
    timer.Dispose();
    tcs.TrySetResult(DateTimeOffset.UtcNow);
 }, null, Timeout.Infinite, Timeout.Infinite);

 tcs = new TaskCompletionSource<DateTimeOffset>(timer);
 timer.Change(millisecondsTimeout, Timeout.Infinite);
 return tcs.Task;
}

以上代码等待超时。我有一个数据库调用,我想以上述方式触发,但对如何编写它有点困惑:

   using (var context = new srdb_sr2_context())
   {
      return context.GetData("100", "a2acfid");
   }

我写了如下函数,但不确定这是否是正确的做法

TaskCompletionSource<IList<InstructorsOut>> tcs = null;
        Timer timer = null;

        timer = new Timer(delegate
        {
            timer.Dispose();

            //prepare for expensive data call
            using (var context = new srdb_sr2_context())
            {
                var output = context.GetData("100", "a2acfid");

                //set the result
                tcs.TrySetResult(output);
            }  

        }, null, Timeout.Infinite, Timeout.Infinite);

        tcs = new TaskCompletionSource<IList<InstructorsOut>>(timer);
        timer.Change(0, Timeout.Infinite);
        return tcs.Task;

任何帮助将不胜感激。

【问题讨论】:

  • 混淆的原因是 TaskCompletionSource 不是关于运行 IO 绑定操作。它是关于为其他异步操作提供基于任务的包装器,例如。计时器延迟、事件、callbakcs。此外,数据库操作不是 IO 绑定操作。他们在等待结果时实际上只有很少的 IO

标签: parallel-processing task-parallel-library async-await c#-5.0 parallel-extensions


【解决方案1】:

您的代码对我来说没有多大意义。如果您想在一段时间后执行代码,Timer 很有用,但这不是您需要的。

如果要在后台线程上执行操作,可以使用Task.Run()

Task<IList<InstructorsOut>> GetDataBackground()
{
    return Task.Run(() =>
    {
        using (var context = new srdb_sr2_context())
        {
            return context.GetData("100", "a2acfid");
        }  
    });
}

以这种方式使用后台线程在您不想阻塞 UI 线程的 UI 应用程序中很有用。但是,如果您有类似 ASP.NET 应用程序,这实际上不会给您任何性能或可伸缩性改进。为此,GetData() 方法必须真正异步。

【讨论】:

  • 这正是我的问题:如何使 GetData() 真正异步。我还添加了 MSDN 链接,该链接显示使用 Timer 来执行此操作。
  • 嗯,你不能(假设你不能直接修改GetData())。包含GetData() 的库的作者必须这样做。
  • GetData() 是实体框架函数导入。所以我不能在那里做任何事情,因为 EF 5.0 不支持异步操作。
  • @SanjaySutar 在这种情况下,你无能为力(除了切换到 EF 6.0)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-06
  • 2011-11-14
相关资源
最近更新 更多