gpt4 book ai didi

带锁的C#多线程导致死锁

转载 作者:太空宇宙 更新时间:2023-11-03 16:01:25 24 4
gpt4 key购买 nike

我在任务中运行了这段代码:

foreach (a in as) // yield return
{
component.Notify(...); // This component locks internally.
component.PropertyChanged += (o, args) =>
{
// Cancel out of task by adding another screen.
MainWindow.AddContent(new OtherComponent()); // WPF
}
}

现在,当任务在错误的时刻取消时,.Notify 函数在它已经取消后仍会被调用,因为任务仍在运行。我想要的是,当调用 .PropertyChanged 事件时,之后不应再调用 .Notify。我当然可以在循环中用一个相当简单的 bool 值来解决这个问题,它会在下一次迭代中取消这个,比如:

foreach (a in as) // yield return
{
if (requestCancel)
return;
component.Notify(...); // This component locks internally.
component.PropertyChanged += (o, args) =>
{
requestCancel = true;
}
}

这里的一个问题是 foreach (a in as) 语句可能需要一段时间才能返回下一次迭代,因此它可能需要很长时间才能真正被取消。我尝试在 requestCancel 操作周围加锁,然后检查 requestCancel 是否为真,但这会导致死锁,因为 component 在内部对所有操作使用锁。我无法更改它,因为它是第三方组件。我还尝试了一个信号量,一个读写器锁,但我总是以死锁告终。比如这样:

foreach (a in as) // yield return
{
_semaphore.WaitOne();
if (requestCancel)
return;

component.Notify(...); // This component locks internally.
component.PropertyChanged += (o, args) =>
{
_semaphore.WaitOne();
requestCancel = true;
}
_semaphore.Release();
}

基本上,.Notify 被阻止是因为 PropertyChanged 仍在执行(由于两者都在内部使用锁)。这反过来导致 PropertyChanged 正在等待信号量或读写器锁,而另一个 block 永远不会释放信号量,因为它正在等待 PropertyChanged 由于锁定而完成。

我真的需要尽快取消这段代码,并且在用户取消后无法再调用 .Notify。在摆弄了一段时间之后,我的想法用完了。如果有任何不清楚的地方,请不要犹豫,询问更多信息。

最佳答案

我认为,所有代码都在一个线程上执行,如下所示:

  1. 输入通知()
  2. 调用 PropertyChanged 处理程序
  3. 离开通知()

在那种情况下,信号量将始终阻塞您的代码,因为在第 2 步中您等待信号量发出信号,但这只会在第 3 步之后发生。试试这个:

foreach (a in as) // yield return
{
component.PropertyChanged += (o, args) => requestCancel = true;

component.Notify(...);

// break out of the loop here to prevent getting next item from the enumerator
if (requestCancel)
break;
}

// do whatever you want to do after cancel
if (requestCancel)
MainWindow.AddContent(new OtherComponent());

关于带锁的C#多线程导致死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21146795/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com