iku*_*sin 2 c# multithreading winrt-async
似乎Monitor在WinRT商店应用程序中无法正常工作.我有以下代码:
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);
}
Run Code Online (Sandbox Code Playgroud)
在输出窗口中,我看到:
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
Run Code Online (Sandbox Code Playgroud)
这意味着Monitor没有锁定关键区域.有没有人知道我做错了什么?
你有效地尝试使用:
lock (lockObject)
{
await Task.Delay(1000);
}
Run Code Online (Sandbox Code Playgroud)
...除了C#编译器不允许你这样做,因为它会被破坏.当你的await表达式完成时,你可以在一个不同的线程上 - 所以当你调用时Monitor.Exit,你可能不会在你获得锁定的同一个线程上...因此异常.
我建议您更改日志以显示:
In,你正在使用什么线程以及taken之后的值(你可能会看到一些任务没有成功占用监视器,因为另一个线程拥有它 - 但见下文)Monitor.Exit,你在用什么线程目前还不清楚你想要实现什么,但Monitor在这里使用几乎肯定是错误的方法.
还要注意,因为多个任务都可以在同一个线程上执行(不是同时执行,而是"放弃"线程等待)并且因为监视器是可重入的(一个线程可以多次获取监视器),所以很好地看到获取监视器的多个任务.
重要的是要理解为什么这不起作用 - 并且您了解线程与任务不同.然后你可以尝试开始研究如何实际实现你想要的东西,这几乎肯定不是通过Monitor.