Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# ReaderWriterLockSlim EnterReadLock()超过几个方法,其中一个在BackgroundWorker中运行_C#_Multithreading_Winforms_Locking_Backgroundworker - Fatal编程技术网

C# ReaderWriterLockSlim EnterReadLock()超过几个方法,其中一个在BackgroundWorker中运行

C# ReaderWriterLockSlim EnterReadLock()超过几个方法,其中一个在BackgroundWorker中运行,c#,multithreading,winforms,locking,backgroundworker,C#,Multithreading,Winforms,Locking,Backgroundworker,在我的应用程序中,我使用一个ReaderWriterLockSlim来同步从列表进行的读写操作 在下面的示例中,读取列表是在所有3个子方法中执行的,因此这3个子方法应该打包到ReadLock中。问题是BackgroundWorker调用SubMethod3(因为它包含冗长的计算),因此在BackgroundWorker(单独线程)完成SubMethod3之前,可能会调用main方法1的最后一个块中的exitradlock()。因此,子方法3中的代码实际上不受锁的保护 我考虑的是在每个子方法中使用

在我的应用程序中,我使用一个
ReaderWriterLockSlim
来同步从
列表
进行的读写操作

在下面的示例中,读取列表是在所有3个子方法中执行的,因此这3个子方法应该打包到
ReadLock
中。问题是
BackgroundWorker
调用
SubMethod3
(因为它包含冗长的计算),因此在
BackgroundWorker
(单独线程)完成SubMethod3之前,可能会调用main方法1的最后一个块中的
exitradlock()
。因此,
子方法3
中的代码实际上不受锁的保护

我考虑的是在每个子方法中使用一个锁,因此
Submethod3
将有自己的锁,当
BackgroundWorker
完成时,该锁将被释放。这种方法的问题是,另一个线程可能会进入子方法调用之间,因为每个子方法调用完成后都会释放锁

我的问题是:如何使用
ReadLock
保护更多线程

ReaderWriterLockSlim synchronizationLock = new ReaderWriterLockSlim();

public void MainMethod1()
    {
        synchronizationLock.EnterReadLock();
        try
        {
            SubMethod1(); //Run on UI thread
            SubMethod2(); //Run on UI thread
            myBackgroundWorker.RunWorkerAsync();  
        }
        finally
        {
            synchronizationLock.ExitReadLock();
        }
    }


private void myBackgroundWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            SubMethod3(); //Run on separate thread
        }

总的来说,你运气不好。由于线程相关性,您无法从另一个线程释放锁。如果您试图保持读卡器锁(这将允许工作线程获取自己的读锁),并等待工作线程启动,则获取读卡器锁并通知您,以便您可以在此时释放读锁,如果由于
ReaderWriterLock(Slim)
实现的reader/water公平性,有一个等待的writer线程,那么您将得到一个死锁

我看到以下选项:

(A) 在单独的线程上运行整个
main方法1

(B) 编写并使用您自己的读写器锁实现来支持这种场景

(C) 摆脱
BackgroundWorker
并使用此处描述的
AsyncReaderWriterLock
实现之一切换到
async/await
实现

(D) 由于我注意到UI线程上运行的注释
,仅当且仅当支持封送来自另一个线程的调用的线程使用该方法时(对于WF和WPF UI线程是如此),您可以使用以下技术:

public void MainMethod1()
{
    synchronizationLock.EnterReadLock();
    bool releaseLock = true;
    try
    {
        SubMethod1();
        SubMethod2();
        RunWorkerCompletedEventHandler onRunWorkerCompleted = null;
        onRunWorkerCompleted = (sender, e) =>
        {
            ((BackgroundWorker)sender).RunWorkerCompleted -= onRunWorkerCompleted;
            synchronizationLock.ExitReadLock();
        };
        myBackgroundWorker.RunWorkerCompleted += onRunWorkerCompleted;
        myBackgroundWorker.RunWorkerAsync();
        releaseLock = false;
    }
    finally
    {
        if (releaseLock)
            synchronizationLock.ExitReadLock();
    }
}
请注意,虽然选项(D)似乎在
main方法1
的上下文中解决了该问题,但如果UI线程试图从另一个位置获取读取锁,并且有一个挂起的写入程序等待,则很容易导致死锁


一般来说,从UI线程使用长时间保持锁是一个坏主意,它会导致更多问题,而不是解决问题。在我看来,最好的选项是(A)和(C),到目前为止(A)是最简单的,如果你负担得起的话(如果
SubMethod1
SubMethod2
不需要在UI线程上运行,或者可以对其进行必要的调用)。

Hmm,不,你是从MainMethod1()调用SubMethod3。如果您也从BGW调用它,那么它必须单独使用synchronizationLock。好的,我更新了这个问题,以便更清楚地说明我已经在做什么。@downvoter:为什么?这个问题不清楚,还是我完全错了?没有评论,没有人会变得更聪明。(如果有评论的话,可以询问反对票,尽管根据我的经验,投票人已经离开了,所以这样做没有太大价值。但是我们确实要求不要在帖子中添加这样的评论,因为绝大多数未来读者对这些评论不感兴趣,如果你把它们放进去,人们有时会投反对票)@halfer:好的,谢谢。你能向我解释一下为什么这个问题被否决了吗?即使在你编辑了它之后?没有解释,我也不知道该修改什么,或者将来如何描述这些问题。谢谢你的回答!欧洲已经很晚了,所以我明天早上会仔细研究。约翰,我要更新它,请更新在那之前不要回顾。我最终以不同的方式重写了我的程序,因此这不再是一个问题。我没有设法将你的任何建议应用到我的案例中,但还是非常感谢!