Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.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多线程一些线程似乎没有运行_C#_Multithreading - Fatal编程技术网

C# C多线程一些线程似乎没有运行

C# C多线程一些线程似乎没有运行,c#,multithreading,C#,Multithreading,我有一个项目处理应用程序,我想并行处理多个项目。但是,有时它似乎根本不处理一个项目,有时它处理不止一次。下面是我的代码 在计时器计时时,将创建一个新线程,该线程从数据库中准备一个项目列表,然后锁定每个项目,以便在下一个循环中不会拾取它 SqlConnection connection = GetConnection(); string selectCommand = my_select_command_where_IsLocked_is_null; List<Item> itemLi

我有一个项目处理应用程序,我想并行处理多个项目。但是,有时它似乎根本不处理一个项目,有时它处理不止一次。下面是我的代码

在计时器计时时,将创建一个新线程,该线程从数据库中准备一个项目列表,然后锁定每个项目,以便在下一个循环中不会拾取它

SqlConnection connection = GetConnection();
string selectCommand = my_select_command_where_IsLocked_is_null;
List<Item> itemList = new List<Item>();
using(SqlDataAdapter adapter = new SqlDataAdapter(selectCommand, connection))
{
  using(SqlCommandBuilder cbCommandBuilder = new SqlCommandBuilder(adapter))
  {
    DataTable dtItemStore = new DataTable();
    adapter.Fill(dtItemStore);
    int totalRows = dtItemStore.Rows.Count;
    if(totalRows > 0)
    {
      adapter.UpdateCommand = cbCommandBuilder.GetUpdateCommand();
      foreach(DataRow row in dtItemStore.Rows)
      {
        Item pickedItem = new Item();
        pickedItem.Key = row["Key"].ToString();
        // Set all Item properties
        itemList.Add(pickedItem);
        row["IsLocked"] = 1;
      }
    }
    adapter.Update(dtItemStore);
  }
}
项目处理器功能在循环结束时解锁项目

function ProcessItem(Item pickedItem)
{
  Logger.Log("Let's process !!! " + pickedItem.Key);
  // Item processing code

  UnlockItem(pickedItem); // unlock and write log
}
问题是,过了一段时间,我意识到我的数据库中有太多的锁定项,而且数量还在增加。在特定点登录,我得到如下结果

- Spawn thread: 20779205, ThreadState: Running
- Let's process !!! 20779205
-  Spawn thread: 20779206, ThreadState: Running
- Let's process !!! 20779206
-  Spawn thread: 20779207, ThreadState: Running
- Let's process !!! 20779207
-  Spawn thread: 20779208, ThreadState: Running <---Not processed
- Let's process !!! 20779209                    <---Duplicate 
-  Spawn thread: 20779209, ThreadState: Running
- Let's process !!! 20779209
-  Spawn thread: 20779211, ThreadState: Running <---Not processed
- Let's process !!! 20779213
-  Spawn thread: 20779213, ThreadState: Running
- Let's process !!! 20779228
-  Spawn thread: 20779228, ThreadState: Running
- Let's process !!! 20779231                   
- Let's process !!! 20779231                    <---Duplicate
-  Spawn thread: 20779231, ThreadState: Running
-  Spawn thread: 20779237, ThreadState: Running
- Keys picked: 20779205, 20779206, 20779207, 20779208, 20779209, 20779211,   20779213, 20779228, 20779231, 20779237, 
- Let's process !!! 20779237
- STOP processing. Possible duplicate for 20779209
- STOP processing. Possible duplicate for 20779231
- Unlock Key: 20779209, Row count:1
- Unlock Key: 20779231, Row count:1
- Unlock Key: 20779209, Row count:1
- Unlock Key: 20779237, Row count:1
- Unlock Key: 20779228, Row count:1
- Unlock Key: 20779206, Row count:1
- Unlock Key: 20779207, Row count:1
- Unlock Key: 20779205, Row count:1
- Unlock Key: 20779231, Row count:1
在这里,我可以看到有时候ProcessItem没有被点击20779208、20779211。我不明白为什么这会是。。。花了两天的时间,我完全迷路了

这是多线程环境中的典型情况吗?我怎样才能更好地处理这件事?我必须确保每个项目都处理一次,而且只处理一次

此外,我意识到有时同一个项目会被多次处理20779209、20779231,但是,为了避免重复,我在ProcessItem函数中处理了它。这两种情况之间有联系吗

我做错了什么?

日志显示,在执行委托{ProcessItempickedItem;}之前,foreach循环将pickedItem分配给下一个值

您应该在foreach循环和ProcessItem函数之间使用同步系统或添加同步系统。

从拾取的输出行键:20779205、20779206、20779209、20779211、20779213、20779228、20779231、20779237,我可以断定所有项目都被击中一次

可能您应该将代码修改为:

var keyList = "";
foreach(Item pickedItem in itemList)
{
  Thread.Sleep(15); // Just to delay a bit
  Item tmpItem = pickedItem; -- the same variable should not be accessed by many threads
  var newThread = new Thread(delegate() { ProcessItem(tmpItem); });
  newThread.Start();
  Logger.Log(" Spawn thread: " + pickedItem.Key + ", ThreadState: " + newThread.ThreadState);
  keyList = keyList + pickedItem.Key;
}
Logger.Log("Keys picked: " + keyList);

您真的需要“手动”生成线程吗? 将此任务留给框架执行:

itemList.AsParallel().ForAll((item) =>
{
    Logger.Log("Processing item ...");
    ProcessItem(item);
});
现在您需要做的就是确保ProcessItem方法是线程安全的

编辑
ForAll将阻止当前线程,直到集合中每个项目的操作完成。

是否可能在检索项目后但在将其更新为锁定之前,计时器再次启动?您是否确认该字段已设置为锁定?SQL Profiler在DB上显示的查询顺序是什么?@MattC,是的,计时器可能正在启动,但在这种情况下,我使用IsProcessRunning字段跳过该进程。。。我将更新我的代码。是的,行被锁定了。我会检查分析器…你在循环中标记你更改的迭代器行?!?!?!作为IsLocked,但是检查行是否被锁定的代码在哪里?@PaulZahra,检查在我的查询中我的_select_命令中,其中_IsLocked_为空,类似于从IsLocked为空的项目中选择*。谢谢你的建议。以前没有做太多的线程。。。几乎是一个学习者。我当然会尝试一下。看起来在C5中foreach已经更改,因此不再需要声明局部变量:
itemList.AsParallel().ForAll((item) =>
{
    Logger.Log("Processing item ...");
    ProcessItem(item);
});