可以在使用语句中调用Task.Run吗?

时间:2016-11-15 22:23:32

标签: .net task-parallel-library

这样的代码,我想将大部分工作放在Task.Run中,但我不确定using语句是否仍能按预期工作。

using(MemoryStream ms = new MemoryStream())
{
    Task.Run(() => 
    { 
         /* capture ms and process the stream */ 
    }
}  // Will ms will be disposed here automatically?

感谢。

3 个答案:

答案 0 :(得分:5)

否 - 在您的任务完成运行之前,可以运行流处理。如果可以的话,最好将使用放在任务中,或者在任务结束时手动处理处理。

LIMIT

请注意,如果您正在使用任务之外的内存流,那么您将面临处置后使用它的风险。如果可以,只使用任务中的流并将结果保存到其他地方。

var ms = new MemoryStream();
Task.Run(() =>
{
    /* capture ms and process the stream */

    // Dispose of the stream manually when you are done
    ms.Dispose();
}

答案 1 :(得分:3)

在任务完成之前,流很可能会被关闭并处理掉。以下抛出ObjectDisposedException:

using(MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes("abc"),0,3))
{
    Task.Run(() => 
    { 
         Thread.Sleep(100);
         ms.Read(new byte[3], 0, 3);
    });
}

你可以将using语句移动到任务闭包中你可以等待这样的任务:

using(MemoryStream ms = new MemoryStream(Encoding.ASCII.GetBytes("abc"),0,3))
{
    await Task.Run(() => 
    { 
         Thread.Sleep(100);
         var bytes = new byte[3];
         ms.Read(bytes, 0, 3);
         Console.WriteLine(Encoding.ASCII.GetString(bytes));
    });
}

答案 2 :(得分:1)

除了上述两个变体之外,如何使用ContinueWith进行处置?当您将任务实现作为委托传递而不是内联实现时,这特别有用:

var ms = new MemoryStream();
Task.Run(TaskUsingMemoryStream).ContinueWith(task => ms.Dispose());

您可能会争辩说,如果您在任务完成后立即处置它,那么为什么要在任务外部创建内存流,但是鉴于OP正在执行的操作,我认为在更大的范围内对此有一定的逻辑。它认为所有答案都质疑了这一选择。