由于Result导致任务死锁
本文关键字:任务 死锁 Result 由于 | 更新日期: 2023-09-27 18:00:41
我有以下结构:一个基类异步执行一些加载任务,一个继承类只将基类的结果转换为特殊的数据类型(它只是一个带有一些扩展的通用版本,但这些扩展并不重要)。
我最初调用继承类"处理方法:"
public TOut Process(object parameters)
{
return (TOut) StartProcessor(parameters).Result;
}
此方法调用以下基本方法:
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;
}
当然,现在继承类的Process方法由于Result属性而死锁。但是我怎么能避免这种情况呢?我看到很多文章都非常适合void方法。但我有一些东西必须回到主叫班。我必须在Process方法中返回Task吗?我该怎么做才能使它异步运行,同时在最后仍然返回对象?
我真的不明白。。。使用void方法很简单,但由于我需要获得此任务的结果,它会死锁。我不明白这应该如何工作:-/
编辑:很明显。。。
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;
});
}
感谢
我必须在Process方法中返回Task吗?
这是最好的解决方案,是的:
public Task<TOut> ProcessAsync(object parameters)
{
return StartProcessorAsync(parameters);
}
我该怎么做才能使它异步运行,同时在最后仍然返回对象?
这两种说法放在一起没有意义。想想看,你希望它异步运行,但同步运行返回结果。
最好的解决方案是允许代码异步。如果StartProcessorAsync
是异步的,那么调用它的所有东西也应该是异步的。这是编写异步代码的自然方式。
有各种各样的黑客试图使异步工作同步,但没有一种在所有场景中都有效,因为在某种程度上,这些黑客中的每一种都必须试图迫使异步工作同步完成。这根本不起作用;最好的解决方案是允许异步工作是异步的。