结果导致任务死锁 [英] Task deadlocks because of Result

查看:102
本文介绍了结果导致任务死锁的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我具有以下构造:一个基类,它异步执行一些加载任务;一个继承的类,它仅将基类的结果转换为特殊的数据类型(它是具有某些扩展名的通用版本,但是这些都不重要).

I have the following construct: A base-class which does some loading tasks asynchronously and a inherited class which only converts the result of the base-class into a special data-type (it's just a generic version with some extensions, but those are not of importance).

我最初将继承的类称为处理方法":

I initially call the inherited class' Process-method:

    public TOut Process(object parameters)
    {
        return (TOut) StartProcessor(parameters).Result;
    }

此方法调用基础的以下方法:

This method calls the following method of the base:

    protected async Task<object> StartProcessor(object parameters)
    {
        if (State == PipelineState.Running) return null;
        if (!ValidatePipeline())
        {
            Logging.Error(
                "Pipeline can't start processor: There are some broken segment chain-links. Check your segment settings.");
            return null;
        }

        State = PipelineState.Running;
        _stopwatch.Start();

        object result = await Task.Run(() => RunPipeline(parameters));

        _stopwatch.Stop();

        if (result is PipelineState)
            State = (PipelineState) result;
        State = result != null ? PipelineState.Finished : PipelineState.Failed;

        RecentProcessTime = _stopwatch.Elapsed;
        _stopwatch.Reset();
        Logging.Debug("Finished process for pipeline {0} in: {1} ms.", Identifier,
            RecentProcessTime.TotalMilliseconds);

        return result;
    }

    private object RunPipeline(object parameter)
    {
        object recentResult = null;
        for (int i = 0; i < SegmentCount; i++)
        {
            if (_cancelProcess) // Cancel process
                return PipelineState.Cancelled;

            PipelineSegmentBase seg = Segments[i];
            if (i == 0) // If first, do initial process
            {
                recentResult = seg.Process(parameter, ProcessingDirection);
                continue;
            }
            if (i > 0 && recentResult == null) // If not first and recent result was null, process failed
                return PipelineState.Failed;

            seg.Process(recentResult, ProcessingDirection); // Process
        }

        return recentResult ?? PipelineState.Failed;
    }

现在,由于Result-property,现在当然继承了类的Process-method死锁.但是,我该如何避免这种情况呢?我看到了很多有关无效方法的文章.但是我得到了一些必须返回主讲课的东西.我必须在处理方法中返回任务吗?我该怎么办,以使其异步运行,同时仍在最后返回对象?

Now, of course, the inherited class' Process-method deadlocks because of the Result-property. But how the heck can I avoid this? I saw a lot of articles which were great for void-methods. But I got something I have to return to the calling class. Must I return a Task in the Process-method? What can I do so that this runs asynchronously whilst it still returns the object at the end?

我真的不明白...用空方法很简单,但是由于我需要获取此任务的结果,所以它陷入了僵局.我不知道这应该怎么工作:-/

I really don't understand that... With void-methods it's simple, but as I need to get the Result of this task, it deadlocks. I don't get how this should ever work :-/

在这里显然发生了...

Here it happens obviously...

    public override object Process(object input, PipelineDirection direction)
    {
        if (!IsValidInput(input)) return null;
        Stream str = (Stream) input;
        // DEADLOCK
        return Core.IDE.GetGUICore().GetUIDispatcher().Invoke(() =>
        {
            Image i = new Image();
            i.BeginInit();
            i.Source = BitmapFrame.Create(str);
            i.EndInit();
            return i;
        });
    }

谢谢

推荐答案

我必须以处理方法返回任务吗?

Must I return a Task in the Process-method?

那是最好的解决方案,是的:

That's the best solution, yes:

public Task<TOut> ProcessAsync(object parameters)
{
    return StartProcessorAsync(parameters);
}

我该怎么办,以使其异步运行,同时仍在最后返回对象?

What can I do so that this runs asynchronously whilst it still returns the object at the end?

这两个语句在一起没有意义.想一想.您希望它异步运行,而同步返回结果.

Those two statements don't make sense together. Think about it. You want it to run asynchronously and yet synchronously return the result.

最好的解决方案是允许代码异步.如果StartProcessorAsync是异步的,那么调用它的所有内容也应该是异步的.这是编写异步代码的自然方法.

The best solution is to allow the code to be asynchronous. If StartProcessorAsync is asynchronous, then everything that calls it should be asynchronous, too. This is the natural way to write asynchronous code.

有各种各样的方法可以尝试同步异步,但是它们都不在所有情况下都可以工作-因为以某种方式,这些黑客中的每一个都必须设法强制异步工作同步完成.那只是行不通;最好的解决方案是允许异步工作是异步的.

There are various hacks to try to get synchronous over asynchronous working, but none of them work in all scenarios - because, in some way, every one of those hacks must try to force the asynchronous work to complete synchronously. That just doesn't work cleanly; the best solution is to allow asynchronous work to be asynchronous.

这篇关于结果导致任务死锁的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆