Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/320.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# 阻止并发访问线程池_C#_Multithreading - Fatal编程技术网

C# 阻止并发访问线程池

C# 阻止并发访问线程池,c#,multithreading,C#,Multithreading,因此,我正在运行一个查询并使用一个名为StartJob的函数处理并发返回的行,该函数将用于我的作业: ThreadPool.QueueUserWorkItem(StartJob, job); 工作非常好,速度非常快。但是现在我被告知当查询返回时,一些行可能具有相同的job.UserID值,并且我们不能同时为相同的job.UserID值运行StartJob函数。问题是:在具有相同用户ID的StartJob的任何其他实例完成之前,如何执行StartJob块 我确信有一种方法可以获得每个用户ID的锁

因此,我正在运行一个查询并使用一个名为StartJob的函数处理并发返回的行,该函数将用于我的作业

ThreadPool.QueueUserWorkItem(StartJob, job);
工作非常好,速度非常快。但是现在我被告知当查询返回时,一些行可能具有相同的job.UserID值,并且我们不能同时为相同的job.UserID值运行StartJob函数。问题是:在具有相同用户ID的StartJob的任何其他实例完成之前,如何执行StartJob块

我确信有一种方法可以获得每个用户ID的锁,但我不知道怎么做。谢谢您的帮助。

HashSet hs=new HashSet();//与所有线程相同
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);
    }
}
int id=1;//你的身份证 //这是你的线体。你可以根据自己的需要传递id。 //它的闭包,或作为线程的参数。 //这将从短旋转开始,每次尝试将id添加到哈希集中。 //当lambda函数返回true时,SpinUntil停止。 SpinWait.SpinUntil(()=> { 锁(cd) { 返回hs.Add(id); } }); //或者,如果您知道操作很慢,或者<.NET 4.0 //这更清楚。该线程将在可以将id添加到哈希集之前进行让步。 while(true) { 锁(hs) { 如果(hs.添加(id)) { 打破 } } 螺纹屈服强度(); } //变体的结尾 //记住试试/最后!这在例外情况下很重要!!! 尝试 { //把你的密码放在这里 //把你的密码放在这里 //把你的密码放在这里 } 最后 { 锁(hs) { hs.移除(id); } }
两个版本,一个适合缩写
StartJob
,仅适用于.NET 4.0,另一个适用于.NET>=3.5

显然,
hs
在所有线程之间是通用的,而
id
job.UserID


我将在.NET4.0下添加,您可以使用
SpinLock
而不是
lock
。它有点快,但语法有点复杂。

使用任务并行库

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));                  
}
var tasks=newdictionary();
队列作业(作业作业)
{
锁定(任务)
if(tasks.ContainsKey(job.UserID))
{
var newTask=tasks[job.UserID].ContinueWith(=>StartJob(job));
任务[job.UserID]=newTask;
}
其他的
tasks[job.UserID]=Task.Factory.StartNew(()=>StartJob(job));
}

如果您使用相同的job.UserID运行StartJob,直到它指向某个共享资源(如数据库中的文件或行),将不会出现并发冲突。你能展示一下你在StartJob做什么吗?什么版本的.NET?3.5或4.0?@完全正确,我在StartJob中运行了更多的查询,这些查询会锁定用户ID拥有的行,因此我们会看到超时,因为这些长时间运行的查询会锁定这些行。因此,我想用一些特定于UserID的锁启动StartJob,并在那里阻塞,直到释放为止。如果你必须用相同的id对同一行执行相同的操作,这不是相同的操作吗?我的意思是,为什么你需要多次这样做?也许你只需要删除副本?不是任务。继续,最后一个任务。ContinueWith@xanatos那是不可能的。试试看,对。。。和
var newTask=lastTask.ContinueWith(=>StartJob(job))