如何获取Exception的上下文

问题描述 投票:1回答:1

我使用的是 TaskParallelLibrary DataFlow 结合 Try 由Stephen Cleary设计的图书馆(https:/github.comStephenClearyTry。)来实现所谓的 "铁路编程",这样我就可以通过。Exception 数据下管。我想知道,如果它是以某种方式可以在 ActionBlock 以获得一些背景资料,以了解是什么或(在我的情况下)到底是哪个项目引起的。Exception这里有一个小的示例代码,我使用的是TaskParallelLibrary DataFlow结合Stephen Cleary设计的Try库(https/github comStehenClearyTry),实现了所谓的 "铁路编程"。

public async Task TestRailroadException(List<int> constructIds)
{
    var downloadBlock = new TransformBlock<int, Try<int>>(
        construct => Try.Create(() =>
    {
        //ThisMethodMyThrowException();
        return 1;
    }));

    var processBlock = new TransformBlock<Try<int>, Try<int>>(
        construct => construct.Map(value =>
    {
        //ThisMethodMyAlsoThrowException();
        return 1;
    }));

    var resultsBlock = new ActionBlock<Try<int>>(construct =>
    {
        if (construct.IsException)
        {
            var type = construct.Exception.GetType();
            //Here it would be nice to know which item(id) was faulted.
        }
    });
    downloadBlock.LinkTo(processBlock, new DataflowLinkOptions
        { PropagateCompletion = true });
    processBlock.LinkTo(resultsBlock, new DataflowLinkOptions
        { PropagateCompletion = true });
    foreach (var constructId in constructIds)
    {
        await downloadBlock.SendAsync(constructId);
    }

    downloadBlock.Complete();
    await resultsBlock.Completion;
}
c# task-parallel-library pipeline tpl-dataflow
1个回答
1
投票

你可以使用 ValueTuple<TId, Try<TResult>> 结构作为管道的消息,但如果创建一个自定义包装的 Try 类,该类也持有id。由于这个包装器会有两个类型参数,所以允许将其命名为 Try 也是。

public readonly struct Try<TId, TResult>
{
    public static Try<TId, TResult> Create(TId id, Func<TResult> func)
        => new Try<TId, TResult>(id, Try.Create(func));

    public static async Task<Try<TId, TResult>> Create(TId id,
        Func<Task<TResult>> func)
        => new Try<TId, TResult>(id, await Try.Create(func).ConfigureAwait(false));

    public readonly TId Id { get; }
    public readonly Try<TResult> Result { get; }

    private Try(TId id, Try<TResult> result) { Id = id; Result = result; }

    public Try<TId, TNewResult> Map<TNewResult>(Func<TResult, TNewResult> func)
        => new Try<TId, TNewResult>(Id, Result.Map(func));

    public async Task<Try<TId, TNewResult>> Map<TNewResult>(
        Func<TResult, Task<TNewResult>> func)
        => new Try<TId, TNewResult>(Id, await Result.Map(func).ConfigureAwait(false));
}

你可以这样使用它:

var downloadBlock = new TransformBlock<int, Try<int, int>>(
    construct => Try<int, int>.Create(construct, async () =>
{
    await SometimesThrowsAsync();
    return 1;
}));

var processBlock = new TransformBlock<Try<int, int>, Try<int, int>>(
    construct => construct.Map(async value =>
{
    await SometimesThrowsAsync();
    return 1;
}));

var resultsBlock = new ActionBlock<Try<int, int>>(construct =>
{
    if (construct.Result.IsException)
    {
        var type = construct.Result.Exception.GetType();
        //Log that the {construct.Id} has failed.
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.