多个使用者不一致地更新结果数组

问题描述

我有一个文件,每一行都可以分别处理,因此我启动了一个阅读器和多个解析器。

每个解析器会将结果写回到结果持有者数组中,以进行进一步处理。

我发现如果我启动更多的解析器,则无论我使用ConcurrentQueue还是BlockingCollection或其他一些东西,结果持有人数组每次都会提供不同的内容

我反复运行该程序并多次输出结果数组,如果使用多个解析器,每次都会给出不同的结果。

string[] result = new string[nRow];
static BlockingCollection<queueItem> myBlk = new BlockingCollection<queueItem>();

static void Main()
{
    Reader();
}

static void parserThread()
{
    while (myBlk.IsCompleted == false)
    {
        queueItem one;

        if (myBlk.TryTake(out one) == false)
        {
            System.Threading.Thread.Sleep(tSleep);
        }
        else
        {
            oneDaTarow(one.seqIndex,one.line);
        }
    }
}

static void oneDaTarow(int rowIndex,string line)
{
    result[rowIndex] = // some process with line
}

static void Reader()
{
    for (int i = 0; i < 10; i++)
    {
        Task t = new Task(() => parserThread());
        t.Start();
    }

    StreamReader sr = new StreamReader(path);
    string line;
  
    int nRead=0;
    while((line = sr.ReadLine()) != null)
    {
        string innerLine = line;
        int innerN = nRead;
        myBlk.Add(new queueItem(innerN,innerLine));
        nRead++;
    }
    siteBlk.CompleteAdding();
    sw.close();

    while (myBlk.IsCompleted == false)
    {
        System.Threading.Thread.Sleep(tSleep);
    }
}

class queueItem
{
    public int seqIndex = 0;
    public string line = "";
    public queueItem(int RowOrder,string content)
    {
        seqIndex = RowOrder;
        line = content;
    }
}

解决方法

等待过程完成的方式有问题:

Container(
  child: Wrap(
    children: <Widget>[
      ListTile(
          leading: Icon(Icons.camera_enhance),title: Text(getTranslated(context,"Camera")),onTap: () async {
            var status = await Permission.camera.status;
            if (status.isGranted) {
              final pickedFile =
                  await _picker.getImage(source: ImageSource.camera);
              final File file = File(pickedFile.path);
              imageSelected(file);
            } else if (status.isUndetermined) {
              final pickedFile =
                  await _picker.getImage(source: ImageSource.camera);
              final File file = File(pickedFile.path);
              imageSelected(file);
            } else {
              showDialog(
                  context: context,builder: (BuildContext context) => CupertinoAlertDialog(
                        title: Text('Camera Permission'),content: Text(
                            'This app needs camera access to take pictures for upload user profile photo'),actions: <Widget>[
                          CupertinoDialogAction(
                            child: Text('Deny'),onPressed: () => Navigator.of(context).pop(),),CupertinoDialogAction(
                            child: Text('Settings'),onPressed: () => openAppSettings(),],));
            }
          }),)

以下是IsCompleted属性的描述:

获取此while (myBlk.IsCompleted == false) { System.Threading.Thread.Sleep(tSleep); } 是否已标记为添加完成并且为空。

在您的情况下,BlockingCollection<T>的完成不应表示整个操作已完成,因为从集合中获取的最后几行可能尚未处理。

相反,您应该将辅助任务存储到数组(或列表)中,并等待它们完成。

BlockingCollection

通常,除了记录调试信息以外,您几乎不应该将Task.WaitAll(tasks); 属性用于其他任何事情。在大多数情况下,使用它来控制执行流程会引入竞争条件。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...