2011-10-06 74 views
3

所以我運行一個查詢和處理在返回同時使用一個名爲StartJob功能,將在我的工作工作行:阻止併發訪問的線程池

ThreadPool.QueueUserWorkItem(StartJob, job); 

的偉大工程,是非常快。但是現在我被告知當查詢返回時,某些行可能具有與job.UserID相同的值,並且我們無法同時爲相同的job.UserID值運行StartJob函數。問題是:如何使StartJob塊執行,直到具有相同用戶ID的StartJob的任何其他實例都已完成?

我確定有一種方法可以獲得每個用戶ID鎖,但我不知道該怎麼做。謝謝您的幫助。

+0

將不會有併發衝突如果您用同樣的job.UserID StartJob,直到它的目標是像一個文件中的一些共享資源或數據庫行。你可以在StartJob中展示你在做什麼? –

+0

什麼版本的.NET? 3.5還是4.0? – xanatos

+0

@invisible完全正確,我在StartJob中運行了更多查詢,鎖定了UserID所擁有的行,因此我們看到超時,因爲這些長時間運行的查詢正在鎖定這些行。所以我想用一些特定於UserID的鎖來啓動StartJob,並在那裏自由地阻止它。 – powlette

回答

1
HashSet<int> hs = new HashSet<int>(); // In common with all the threads 

int id = 1; // Your id 

// This is the body of your Thread. You pass it the id as you want. 
// A closure on it, or as a parameter of the thread. 

// This will begin with short spins, every time trying to add the id to the hashset. 
// SpinUntil stops when the lambda function returns true. 
SpinWait.SpinUntil(() => 
{ 
    lock (cd) 
    { 
     return hs.Add(id); 
    } 
}); 

// OR, if you know the operation is slow, or < .NET 4.0 

// This is clearer. The thread yields until it can add the id to the hashset. 
while (true) 
{ 
    lock (hs) 
    { 
     if (hs.Add(id)) 
     { 
      break; 
     } 
    } 

    Thread.Yield(); 
} 

// End of the variant 

// Remember the try/finally! It's important in case of exceptions!!! 
try 
{ 
    // Put here your code 
    // Put here your code 
    // Put here your code 
} 
finally 
{ 
    lock (hs) 
    { 
     hs.Remove(id); 
    } 
} 

兩個版本,一個是好短StartJob和只適用於.NET 4.0,一個與.NET> = 3.5的作品。

顯然hs在所有線程之間是相同的,並且idjob.UserID

我將在.NET 4.0中加入,您可以使用SpinLock而不是lock。它有點快,但它的語法有點棘手。

1

使用任務並行庫

var tasks = new Dictionary<int, Task>(); 

QueueJob(Job job) 
{ 
    lock(tasks) 
     if (tasks.ContainsKey(job.UserID)) 
     { 
     var newTask = tasks[job.UserID].ContinueWith(_=>StartJob(job)); 
     tasks[job.UserID] = newTask; 
     } 
     else 
      tasks[job.UserID] = Task.Factory.StartNew(()=>StartJob(job));     
} 
+0

不是task.ContinueWith,lastTask.ContinueWith – xanatos

+0

@xanatos yea修復了它。謝謝。 –

+0

+1可能更可讀爲http://pastebin.com/Hreck9VE – xanatos