具有多个线程的AutoResetEvent

时间:2017-07-06 15:07:44

标签: c# .net multithreading

我有一个带有SQL后端的多用户应用程序。某些关键数据需要在用户之间保持最新,因此我对这些集合类进行了后台刷新。我当前的刷新代码如下。

public virtual bool Refresh()
{
    if (SetRefreshThread() == RefreshLockStatus.AlreadyRefreshing) {
        DebugLogging("Checking for refresh thread lock", ClassDebugLevel.CollectionRefresh);
        if (RefreshLock.WaitOne(5000) == false) {
            DebugLogging("Refresh in already in progress on another thread.  Aborting refresh");
            return false;
        } else {
            DebugLogging("Finished refreshing on other thread so not refreshing again");
            return true;
        }
    }
    DebugLogging("Refresh Starting");
    //Refresh code here
    DebugLogging("Finished refreshing");
    ClearRefreshThread();
    return true;
}
protected RefreshLockStatus SetRefreshThread()
{
    lock (RefreshSyncLock) {
        if (_RefreshThread != null) {
            return RefreshLockStatus.AlreadyRefreshing;
        }
        _RefreshThread = Threading.Thread.CurrentThread;
        RefreshLock.Reset();
        return RefreshLockStatus.Allowed;
    }
}
protected void ClearRefreshThread()
{
    lock (RefreshSyncLock) {
        _RefreshThread = null;
        RefreshLock.Set();
    }
}
private readonly Threading.AutoResetEvent RefreshLock = new Threading.AutoResetEvent(true);

当单个线程调用时,这个工作正常,我得到了日志:

2017-07-06 07:13:55.272294 Thread #010 Collection1->Refresh Starting
2017-07-06 07:13:55.323755 Thread #010 Collection1->Finished refreshing

在两个主题上,我也得到了预期的结果:

2017-07-06 07:13:55.272294 Thread #010 Collection1->Refresh Starting
2017-07-06 07:13:55.272294 Thread #011 Collection1->Checking for refresh thread lock
2017-07-06 07:13:55.323755 Thread #010 Collection1->Finished refreshing
2017-07-06 07:13:55.325258 Thread #011 Collection1->Finished refreshing on other thread so not refreshing again

在三个线程上,第三个线程超时而不是在第一个线程

时完成
2017-07-06 07:13:55.272294 Thread #010 Collection1->Refresh Starting
2017-07-06 07:13:55.272294 Thread #011 Collection1->Checking for refresh thread lock
2017-07-06 07:13:55.272294 Thread #014 Collection1->Checking for refresh thread lock
2017-07-06 07:13:55.323755 Thread #010 Collection1->Finished refreshing
2017-07-06 07:13:55.325258 Thread #011 Collection1->Finished refreshing on other thread so not refreshing again
2017-07-06 07:14:00.872013 Thread #014 Collection1->Refresh in already in progress on another thread.  Aborting refresh

我的目标是,如果刷新在一个线程上启动,并且在执行时,其他线程想要刷新相同的数据,它们都等待第一个线程完成,然后全部返回true。是否有更好的同步对象来实现我想要的目标?

1 个答案:

答案 0 :(得分:0)

似乎当同一个WaitOne方法暂停多个线程时,Set方法将允许其中一个线程通过,但不是全部。

由于我的目标是返回就像方法已经完成一样,我只需要在WaitOne之后在分支上添加另一个Set。

public virtual bool Refresh()
{
    if (SetRefreshThread() == RefreshLockStatus.AlreadyRefreshing) {
        DebugLogging("Checking for refresh thread lock", ClassDebugLevel.CollectionRefresh);
        if (RefreshLock.WaitOne(5000) == false) {
            DebugLogging("Refresh in already in progress on another thread.  Aborting refresh");
            return false;
        } else {
            DebugLogging("Finished refreshing on other thread so not refreshing again");
            RefreshLock.Set //Let next thread that is waiting pass
            return true;
        }
    }
    DebugLogging("Refresh Starting");
    //Refresh code here
    DebugLogging("Finished refreshing");
    ClearRefreshThread();
    return true;
}

这给了我想要的日志

2017-07-07 06:35:28.115506 Thread #011 Collection1->Refresh Starting
2017-07-07 06:35:28.115506 Thread #014 Collection1->Checking for refresh thread lock
2017-07-07 06:35:28.115506 Thread #010 Collection1->Checking for refresh thread lock
2017-07-07 06:35:28.203229 Thread #011 Collection1->Finished refreshing
2017-07-07 06:35:28.204233 Thread #010 Collection1->Finished refreshing on other thread so not refreshing again
2017-07-07 06:35:28.204734 Thread #014 Collection1->Finished refreshing on other thread so not refreshing again