C# 等待似乎不是等待
我创建了一个用于重用线程的类。此类有一个用于将作业排队的公共方法C# 等待似乎不是等待,c#,C#,我创建了一个用于重用线程的类。此类有一个用于将作业排队的公共方法 public AwaitableJob<T> PrepareJob(Func<T> job) { lock (locker) { var aj = new AwaitableJob<T>(job); taskQueue.Enqueue(aj); System.Threading.Mon
public AwaitableJob<T> PrepareJob(Func<T> job)
{
lock (locker)
{
var aj = new AwaitableJob<T>(job);
taskQueue.Enqueue(aj);
System.Threading.Monitor.PulseAll(locker);
return aj;
}
}
但它不是等待,而是继续执行,所以atm变量总是空的。当我在AwatiableJob中添加断点时,它显示在IsCompleted设置为true之前调用了GetResult。有人知道哪里会出问题吗?谢谢您的帮助。问题出在这里:
public void OnCompleted(Action continuation)
{
continuation.Invoke();
}
OnCompleted
的要点是注册一个回调,当它完成时,但是您现在正在调用continuation。您唯一应该这样做的时间是针对线程竞争条件,其中有人检查IsCompleted
并获得false
,但状态在这和注册回调之间发生更改。除此之外,您应该做的是存储回调,并从实际改变状态的代码中调用它(看起来像您的代码>调用/<代码>方法),再次记住在切换时考虑线程安全性。
坦率地说,如果这听起来很复杂:使用
TaskCompletionSource
重用线程可能会有问题。有些设置是特定于线程的,因此它们会在作业中保持不变(我想到了文化)。您确定需要实现自己的线程池吗?与现有线程池方法不同的是,我强烈建议不要创建自己的等待对象。在极少数情况下这是合适的,而这不是其中之一。您应该在任何时候使用Task
来获得可等待的对象。这可能是使用async void
的问题async void
实际上只适用于事件处理程序,而不是您需要确保等待整个任务的任何东西。使用async Task
作为返回类型,不返回任何内容,但仍然能够返回wait@JamesFaix不,这不是async void
方法的结果,而是所示代码中等待对象的不正确实现的结果。我不理解您的INotifyCompletion
实现。您的OnCompleted()
方法应该只注册一个完成回调,它会立即调用该回调。因此,框架自然认为您的等待已经完成,而不是等待。不可能确切地知道发生了什么,因为您没有费心提供一个,当然,您可能不应该实现自己的等待。但是如果你真的想要一个答案,你需要改进这个问题。谢谢你的纠正和解释。现在它等待着。
public async void Connect()
{
var atm = await Worker.PrepareJob(ConnectHelper) as PresentModel;
if (atm == null) return;
var vm = new SwitchingViewModel(atm);
vm.NavigateTo();
}
public void OnCompleted(Action continuation)
{
continuation.Invoke();
}