Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.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
VB.NET,对线程池的并发结果进行排序的最佳实践?_Vb.net_Multithreading_Performance_Concurrency - Fatal编程技术网

VB.NET,对线程池的并发结果进行排序的最佳实践?

VB.NET,对线程池的并发结果进行排序的最佳实践?,vb.net,multithreading,performance,concurrency,Vb.net,Multithreading,Performance,Concurrency,简言之,我试图在使用线程池的传入结果完成时对其进行“排序”。我有一个功能性的解决方案,但在这个世界上没有办法,这是最好的方法(它容易出现巨大的停顿)。我来了!我将尝试重点说明正在发生的事情/需要发生的事情,然后发布我当前的解决方案 代码的目的是获取有关目录中文件的信息,然后将其写入文本文件 我有一个列表(Counter.ListOfFiles),它是以特定方式排序的文件路径列表。这是一本指南,它规定了我需要写入文本文件的顺序 我使用线程池来收集每个文件的信息,创建一个stringbuilder

简言之,我试图在使用线程池的传入结果完成时对其进行“排序”。我有一个功能性的解决方案,但在这个世界上没有办法,这是最好的方法(它容易出现巨大的停顿)。我来了!我将尝试重点说明正在发生的事情/需要发生的事情,然后发布我当前的解决方案

  • 代码的目的是获取有关目录中文件的信息,然后将其写入文本文件

  • 我有一个列表(Counter.ListOfFiles),它是以特定方式排序的文件路径列表。这是一本指南,它规定了我需要写入文本文件的顺序

  • 我使用线程池来收集每个文件的信息,创建一个stringbuilder,其中包含所有准备写入文本文件的文本。然后我调用一个过程(SyncUpdate,包含在下面),从该线程发送stringbuilder(strBld)以及该特定线程刚刚向stringbuilder写入的文件的路径名(Xref)

  • 该过程包括一个同步锁,用于保存所有其他线程,直到找到传递正确信息的线程为止。当线程传递的外部参照与我的列表中的第一项(FirstListItem)匹配时,“正确”信息。当这种情况发生时,我会写入文本文件,删除列表中的第一项,然后在下一个线程中再次执行该操作

我使用显示器的方式可能不太好,事实上,我毫不怀疑我是在以一种攻击性的肆意方式使用它。基本上,当外部参照(来自线程)是我列表中的第一项时,我正在为监视器做一个pulsell。我最初使用的是monitor.wait,但它最终会放弃尝试对列表进行排序,即使在其他地方使用pulse。我可能只是写了一些很尴尬的东西。不管怎样,我认为这不会改变任何事情

基本上,问题归结为监视器将脉冲扫描队列中的所有项目,当我正在寻找的项目很有可能在队列中较早的某个位置传递给它时,它现在将再次对所有项目进行排序,然后再循环查找匹配的条件。这样做的结果是,我的代码将命中其中一个,并需要大量的时间来完成

我愿意相信我只是在工作中使用了错误的工具,或者只是没有正确地使用我拥有的工具。我非常喜欢某种线程解决方案(毫不奇怪,它要快得多!)。今天,我在并行任务功能上有些混乱,很多东西看起来都很有前途,但我在这方面的经验比线程池更少,你们可以看到我是如何滥用它的!也许是排队?你明白了。我没有方向感。如果有人能提出任何建议,我们将不胜感激。谢谢如果您需要任何其他信息,请告诉我

  Private Sub SyncUpdateResource(strBld As Object, Xref As String)
    SyncLock (CType(strBld, StringBuilder))
        Dim FirstListitem As String = counter.ListOfFiles.First
        Do While Xref <> FirstListitem
            FirstListitem = Counter.ListOfFiles.First
    'This makes the code much faster for reasons I can only guess at.
            Thread.Sleep(5)
            Monitor.PulseAll(CType(strBld, StringBuilder))
        Loop
        Dim strVol As String = Form1.Volname
        Dim strLFPPath As String = Form1.txtPathDir
        My.Computer.FileSystem.WriteAllText(strLFPPath & "\" & strVol & ".txt", strBld.ToString, True)
        Counter.ListOfFiles.Remove(Xref)
    End SyncLock
End Sub
Private-Sub-SyncUpdateResource(strBld作为对象,Xref作为字符串)
同步锁(CType(strBld,StringBuilder))
Dim FirstListitem作为字符串=counter.ListOfFiles.First
在外部参照FirstListitem时执行
FirstListitem=Counter.ListOfFiles.First
这使得代码更快,原因我只能猜测。
线程。睡眠(5)
监控脉冲(CType(strBld,StringBuilder))
环
Dim strVol As String=Form1.Volname
Dim STRLFPATH As String=Form1.txtPathDir
My.Computer.FileSystem.writealText(strlfpath&“\”&strVol&“.txt”,strBld.ToString,True)
Counter.ListOfFiles.Remove(外部参照)
端同步
端接头

这是一个非常典型的多生产者、单消费者应用程序。唯一的问题是,在将结果写入输出之前,必须对结果进行排序。这不难做到。让我们先来看看这个需求

NET中实现生产者/消费者关系的最简单方法是使用,这是一个线程安全的FIFO队列。基本上,您可以这样做:

在您的例子中,生产者线程获取项目,执行它们需要的任何处理,然后将项目放入队列。不需要任何显式同步--
BlockingCollection
类实现为您实现了这一点

您的消费者从队列中提取物品并将其输出。你可以在我的文章中看到一个非常简单的例子。(如果您对代码感兴趣,请向下滚动到第三个示例。)该示例仅使用一个生产者和一个消费者,但如果您愿意,可以有N个生产者

您的需求有一点瑕疵,因为消费者不能在获取项目时将其写入文件。它必须确保以正确的顺序书写它们。正如我所说,这并不难做到

您需要的是某种优先级队列,如果项目出现问题,您可以将其放置到该队列中。您的优先级队列可以是一个已排序的列表,如果您期望的无序项目数量不是很大,甚至可以只是一个顺序列表。也就是说,如果您通常一次只有六个可能出现故障的项目,那么顺序列表就可以正常工作

我会使用堆,因为它性能很好。NET框架不提供堆,但我有一个简单的堆,它适合这样的工作。看

下面是我编写消费者的方法(代码是伪C#,但您可能很容易将其转换)

这里的假设是,您有一个名为
sharedQueue
BlockingCollection
,其中包含项目。生产者将项目放入该队列。消费者会这样做:

var heap = new BinaryHeap<ItemType>();
foreach (var item in sharedQueue.GetConsumingEnumerable())
{
    if (item.SequenceKey == expectedSequenceKey)
    {
        // output this item
        // then check the heap to see if other items need to be output
        expectedSequenceKey = expectedSequenceKey + 1;
        while (heap.Count > 0 && heap.Peek().SequenceKey == expectedSequenceKey)
        {
            var heapItem = heap.RemoveRoot();
            // output heapItem
            expectedSequenceKey = expectedSequenceKey + 1;
        }
    }
    else
    {
        // item is out of order
        // put it on the heap
        heap.Insert(item);
    }
}
// if the heap contains items after everything is processed,
// then some error occurred.
var heap=new BinaryHeap();
foreach(sharedQueue.GetConsumingEnumerable()中的变量项)
{
如果(item.SequenceKey==expectedSequenceKey)
{
//输出此项
//然后检查