C#.NET CORE:如果一个返回某种结果,则可以取消其他任务

时间:2019-07-12 15:01:59

标签: c# multitasking .net-core-2.2

如果其中一项返回错误(布尔)结果,如何取消所有任务? 是否可以确定哪个任务返回了结果?

if (auto *op = dyn_cast<CallInst>(&I)) {
    auto function = op->getCalledFunction();
    FunctionType *newFunctionType = FunctionType::get(retType, function->getFunctionType()->params(), false);
    Function *newFunction = (Function *)(F.getParent()->getOrInsertFunction("replacement", newFunctionType));

    std::vector<Value *> arguments;
    CallSite CS(&I);
    CallSite::arg_iterator ait = CS.arg_begin(), aend = CS.arg_end();
    while (ait != aend) {
        Value *arg = (Value *)(&(*ait));
        arguments.push_back(arg);
        ait++;
    }
    ArrayRef<Value *> argArray = ArrayRef<Value *>(arguments);

    IRBuilder<> builder(op);
    Value *newCall = builder.CreateCall(newFunction, argArray);
…}

我尝试使用Task.WaitAll,Task.WaitAny等,但是这些方法均未提供有用的功能(以我为例)。

2 个答案:

答案 0 :(得分:1)

修改:
如@ckuri在评论中所述,利用Task的现有属性比编写自定义结果类要容易得多。相应地调整了我的答案。

一种解决方案是在CreateTask()方法中检查结果,并将CancellationToken传递到您的TaskAction()方法中:

private static Task<bool> CreateTask(CancellationTokenSource cts)
{
    return Task.Run(async () =>
    {
        var result = await TaskAction(cts.Token);

        // If result is false, cancel all tasks
        if (!result)
            cts.Cancel();

        return result;
    });
}

private static async Task<bool> TaskAction(CancellationToken token)
{
    // Check for cancellation
    token.ThrowIfCancellationRequested();

    var delay = Rnd.Next(2, 5);
    // Pass the cancellation token to Task.Delay()
    await Task.Delay(delay * 1000, token);

    var taskResult = Rnd.Next(10) < 4;

    // Check for cancellation
    token.ThrowIfCancellationRequested();

    return taskResult;
}

现在,您可以在Main方法中执行以下操作,以接收未取消的所有任务:

try
{
    // Wait for all tasks inside a try catch block because `WhenAll` throws a `AggregationException` 
    // containing a `TaskCanceledException`, if the token gets canceled
    await Task.WhenAll(tasks);
} 
catch { }

var tasksWithResult = tasks.Where(t => !t.IsCanceled).ToList();

答案 1 :(得分:0)

我手边没有翻译,所以请原谅任何错误。如果您想从任务本身取消所有任务,则您的任务需要访问令牌。有关示例,请参见https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource?view=netcore-3.0。即将其作为参数传递给任务,以便一个任务可以取消其他任务。

    private static async Task<bool> TaskAction(CancellationTokenSource cts)
    {
        var delay = _rnd.Next(2, 5);
        await Task.Delay(delay * 1000);
        var taskResult = _rnd.Next(10) < 4;
        if (!taskResult)
           cts.Cancel()
        return await Task.FromResult(taskResult);
    }

只需确保捕获AggregateException并检查内部例外之一是否为TaskCanceledException