简体   繁体   English

使用WinRT意外行为监视类

[英]Monitor class with WinRT unexpected behaviour

It seems that Monitor doesn't work as expected in WinRT store applications. 似乎Monitor在WinRT商店应用程序中无法正常工作。 I have the following code: 我有以下代码:

protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        var tasks = Enumerable.Range(0, 10).Select((i)=>new Task(DoWork)).ToArray();
        foreach (var task in tasks)
        {
            task.Start();
        }

        Task.WaitAll(tasks);
    }

    static object lockObject = new Object();//typeof(MainPage)

    protected async void DoWork()
    {
        bool taken =false;
        Monitor.Enter(lockObject, ref taken);
        Debug.WriteLine("In");
        await Task.Delay(1000);
        Debug.WriteLine("Out");
        if (taken) Monitor.Exit(lockObject);
    }

In the output window I see: 在输出窗口中,我看到:

In
In
In
In
In
In
In
Out
Out
Out
Out
Out
Out
Out
In
Out
A first chance exception of type 'System.Threading.SynchronizationLockException' occurred in App4.exe

Which mean that Monitor is not locking the critical area. 这意味着Monitor没有锁定关键区域。 Does anybody has a clue what I'm doing wrong? 有没有人知道我做错了什么?

You're effectively trying to use: 有效地尝试使用:

lock (lockObject)
{
    await Task.Delay(1000);
}

... except that the C# compiler wouldn't allow you to do that, because it would be broken. ...除了C#编译器不允许您这样做之外,因为它会损坏。 By the time your await expression completes, you can be on a different thread - so when you call Monitor.Exit , you may well not be on the same thread as you acquired the lock in... hence the exception. 在您的await表达式完成时,您可以位于其他线程上-因此,在调用Monitor.Exit ,您可能与获取锁定的位置不在同一线程上,因此是一个例外。

I suggest that you change your logging to show: 我建议您将日志记录更改为显示:

  • When you call In , what thread you're on and the value of taken afterwards (you'll probably see that some tasks haven't successfully taken the monitor, because another thread owns it - but see below) 当你调用In什么线程你在和的值taken之后(你可能会看到一些任务尚未成功迈出显示器,因为另一个线程拥有它-见下文)
  • Before you call Monitor.Exit , what thread you're on 在你调用Monitor.Exit之前,你正在使用什么线程

It's not clear what you're trying to achieve, but using Monitor here is almost certainly the wrong approach. 目前尚不清楚您要实现的目标,但是在此处使用Monitor几乎可以肯定是错误的方法。

Also note that because multiple tasks can all execute on the same thread (not at the same time, but you're "giving up" the thread with await) and because monitors are reentrant (one thread can acquire a monitor multiple times) you may well see multiple tasks acquiring the monitor. 还要注意,由于多个任务可以全部在同一个线程上执行(而不是同时执行,但是您正在等待线程“放弃”该线程),并且由于监视器是可重入的(一个线程可以多次获取一个监视器),因此您可能很好地看到获取监视器的多个任务。

It's important that you understand why this doesn't work - and that you understand that a thread isn't the same as a task. 重要的是要理解为什么这不起作用 - 并且您了解线程与任务不同。 Then you can try to start working out how to actually achieve what you want, which almost certainly isn't via Monitor . 然后你可以尝试开始研究如何实际实现你想要的东西,这几乎肯定不是通过Monitor

Monitor doesn't work with async methods. Monitor不适用于async方法。

If you want async -compatible mutual exclusion, try SemaphoreSlim.WaitAsync or one of the coordination primitives in my AsyncEx library . 如果您想要async兼容的互斥,请尝试SemaphoreSlim.WaitAsync我的AsyncEx库中的一个协调原语

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM