C#等待似乎没有等待

时间:2018-01-15 21:14:36

标签: c#

我已经创建了重用线程的类。这个类有一个用于排队作业的公共方法。

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;
        }
    }

AwaitableJob是自定义类,它应该提供awaiter对象。

 public class AwaitableJob<T> : INotifyCompletion where T : class
{
    public Func<T> Job { get; private set; }
    public bool IsCompleted { get; private set; } = false;
    private object result;

    public AwaitableJob(Func<T> job)
    {
        this.Job = job;
    }

    public AwaitableJob<T> GetAwaiter()
    {
        return this;
    }

    public void Invoke()
    {
        result = Job.Invoke();
        IsCompleted = true;
    }

    public object GetResult()
    {
        return result;
    }

    public void OnCompleted(Action continuation)
    {
        continuation.Invoke();
    }
}

我试图以这种方式使用它

public async void Connect()
    {
        var atm = await Worker.PrepareJob(ConnectHelper) as PresentModel; 

        if (atm == null) return;
        var vm = new SwitchingViewModel(atm);
        vm.NavigateTo();
    }

但是不是等待它总是继续执行,所以atm变量总是为空。当我在AwaitableJob中添加断点时,它表明在IsCompleted设置为true之前调用了GetResult。谁知道哪里可能有问题?谢谢你的帮助。

1 个答案:

答案 0 :(得分:1)

问题在于:

public void OnCompleted(Action continuation)
{
    continuation.Invoke();
}

OnCompleted的目的是注册 时的回调,但是你现在正在调用 继续 。你应该这样做的唯一时间是线程竞争条件,其中某人检查IsCompleted并获得false,但状态更改之间并注册回调。除此之外,您应该做的是存储回调,并从实际将状态更改为已完成的代码中调用它(看起来像您的{{1} })),再次记住考虑切换时的线程安全性。

坦率地说,如果这听起来很复杂:请使用Invoke