C#任务工厂超时

Rot*_*oto 11 c# factory timeout task

我必须在一个线程中执行一个长的进程操作,并继续将结果返回给一个函数.这是我的代码:

Task<ProductEventArgs>.Factory.StartNew(() =>
    {
        try
        {
             // long operation which return new ProductEventArgs with a list of product

        }
        catch (Exception e)
        {
            return new ProductEventArgs() { E = e };
        }

    }).ContinueWith((x) => handleResult(x.Result), TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

问题实际上我没有超时.我想放一个计时器,以便返回这样的东西:

   new ProductEventArgs() { E = new Exception("timeout") }; 
Run Code Online (Sandbox Code Playgroud)

如果达到超时.不能使用await/async.非常感谢 !

Ste*_*ary 15

你应该使用CancellationTokens:

var cts = new CancellationTokenSource(TimeSpan.FromSeconds(10));
var token = cts.Token;
Task<ProductEventArgs>.Factory.StartNew(() =>
{
    try
    {
        // occasionally, execute this line:
        token.ThrowIfCancellationRequested();
    }
    catch (OperationCanceledException)
    {
        return new ProductEventArgs() { E = new Exception("timeout") };
    }
    catch (Exception e)
    {
        return new ProductEventArgs() { E = e };
    }

}).ContinueWith((x) => handleResult(x.Result), TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

  • 您的代码将在.Net 4.5及更高版本上运行,因为On .Net 4.0,CancellationTokenSource只有默认的Constructor. (3认同)

Kav*_*ian 5

此代码执行您在此处表达的内容:

var timeout = TimeSpan.FromSeconds(5);

var actualTask = new Task<ProductEventArgs>(() =>
{
    var longRunningTask = new Task<ProductEventArgs>(() =>
    {
        try
        {
            Thread.Sleep(TimeSpan.FromSeconds(10)); // simulates the long running computation
            return new ProductEventArgs();
        }
        catch (Exception e)
        {
            return new ProductEventArgs() { E = e };
        }
    }, TaskCreationOptions.LongRunning);

    longRunningTask.Start();

    if (longRunningTask.Wait(timeout)) return longRunningTask.Result;

    return new ProductEventArgs() { E = new Exception("timed out") };
});

actualTask.Start();

actualTask.Wait();

Console.WriteLine("{0}", actualTask.Result.E); // handling E
Run Code Online (Sandbox Code Playgroud)

如您所见longRunningTask,使用TaskCreationOptions.LongRunning选项创建.这样它将专门Thread用于它的执行,并且不会ThreadPool通过占用线程从那里太长时间来干扰正常行为- 这将是其他事物所需要的,例如UI.这对于长时间运行的任务非常重要.

注意:你可以处理actualTask,ContinueWith但我想在这里表达精华.