8

我对多线程有点陌生,过去只玩过它。但我很好奇是否有可能在主线程上有一个字节数组列表,并且在单独的线程中创建新的字节数组时仍然能够添加到该列表中。此外,我将使用一个 for-each 循环,该循环将遍历将用于解析为字节数组的表单列表。所以基本上一个伪代码会是这样的......

reports = new List();

foreach (form in forms)  
{  
    newReport = new Thread(ParseForm(form));  
    reports.Add(newReport);  

}  

void ParseForm(form)  
{  
    newArray = new byte[];  
    newArray = Convert.ToBytes(form);  
    return newArray;  
}

希望上面的伪代码有意义。如果有人能告诉我这是否可行,并指出一个好例子的方向,我相信我能找出实际的代码。

4

4 回答 4

4

在我们意识到它是 .Net 3.5 之前,请保留在 .Net 4 上以供参考

如果您不需要列表中的任何顺序,一个简单的“修复”是使用ConcurrentBag<T>类而不是列表。如果您需要更多订单,还有一个ConcurrentQueue<T>集合。

如果你真的需要更多自定义的东西,你可以使用 BlockingCollection<T> 实现你自己的阻塞集合。 这是一篇关于该主题的好文章。

您也可以使用 Parallel.Foreach 来避免显式创建线程:

private void ParseForms()
{
    var reports = new ConcurrentBag<byte[]>();
    Parallel.ForEach(forms, (form) =>
                                {
                                    reports.Add(ParseForm(form));
                                });

}

private byte[] ParseForm(form)  
{  
    newArray = new byte[];  
    newArray = Convert.ToBytes(form);  
    return newArray;  
}
于 2012-05-16T14:15:05.490 回答
4

如果您需要从多个线程访问一个集合,您应该使用同步,或者SynchronizedCollection如果您的 .NET 版本是 3.0 或更高版本,则使用 a。

这是使您的线程可以访问集合的一种方法:

SynchronizedCollection reports = new SynchronizedCollection();

foreach (form in forms) {  
    var reportThread = new Thread(() => ParseForm(form, reports));
    reportThread.Start();
}

void ParseForm(Form form, SynchronizedCollection reports) {  
    newArray = new byte[];  
    newArray = Convert.ToBytes(form);  
    reports.Add(newArray);
}

如果您使用的是 .NET 4 或更高版本,则命名空间的各种类提供了一种比手动管理线程更好的替代方法System.Threading.Tasks。在决定你的线程实现之前考虑探索这个替代方案。

于 2012-05-16T14:17:04.047 回答
0

下面是一个简单的阻塞集合(仅作为队列),因为您无权访问 C# 4.0,所以我现在刚刚创建了它。它很可能比 4.0 并发集合效率低,但它应该工作得很好。我没有重新实现所有的队列方法,只是入队、出队和窥视。如果您需要其他人并且无法弄清楚它们将如何实施,只需在评论中提及即可。

一旦你有了工作的阻塞集合,你可以简单地从生产者线程添加到它,并使用消费者线程从中删除。

public class MyBlockingQueue<T>
{
    private Queue<T> queue = new Queue<T>();
    private AutoResetEvent signal = new AutoResetEvent(false);
    private object padLock = new object();

    public void Enqueue(T item)
    {
        lock (padLock)
        {
            queue.Enqueue(item);
            signal.Set();
        }
    }

    public T Peek()
    {
        lock (padLock)
        {
            while (queue.Count < 1)
            {
                signal.WaitOne();
            }

            return queue.Peek();
        }
    }

    public T Dequeue()
    {
        lock (padLock)
        {
            while (queue.Count < 1)
            {
                signal.WaitOne();
            }

            return queue.Dequeue();
        }
    }
}
于 2012-05-16T14:49:03.883 回答
0

为什么枚举文件多次返回同一个文件?

检查出。它表明我认为你想做什么。

它在主线程上创建一个列表,然后从另一个线程添加到它。你会需要

using System.Threading.Tasks

-

Files.Clear(); //List<string> 

Task.Factory.StartNew( () =>
{
      this.BeginInvoke( new Action(() =>
         {
            Files.Add("Hi");
         }));
 });
于 2012-05-16T14:12:07.220 回答