2017-07-06 38 views
-1

我有一個帶SQL後端的多用戶應用程序。某些關鍵數據需要在用戶之間保持最新,因此我對這些集合類進行了後臺刷新。我目前的刷新代碼如下。具有多個線程的AutoResetEvent

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。有更好的同步對象來完成我想要的嗎?

+0

日誌對於您正在試圖做(鎖定的關鍵部分,因此只有一個線程可以同時訪問它)是什麼,我認爲它會最好使用'Monitor.TryEnter'和'Monitor.Exit' –

回答

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