问题描述
我有一个大文件,每一行都可以分别处理,因此我启动了一个阅读器和多个解析器。
每个解析器会将结果写回到结果持有者数组中,以进行进一步处理。
我发现如果我启动更多的解析器,则无论我使用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);
属性用于其他任何事情。在大多数情况下,使用它来控制执行流程会引入竞争条件。