【问题标题】:ThreadPool Asynchronised Threads in Same Method同一方法中的 ThreadPool 异步线程
【发布时间】:2023-03-24 11:53:02
【问题描述】:

我有一个关于线程池使用的问题。 在我运行下面的简单代码之后。我得到了结果:

  • ID : 6 --> A
  • ID : 13 --> A
  • ID : 6 --> 2A
  • ID : 12 --> A
  • ID : 13 --> 2A
  • ID : 15 --> A
  • ID : 6 --> 3A
  • ID : 12 --> 2A
  • ID : 14 --> A
  • ID : 13 --> 3A

(继续……) 这是我的代码:

static void Main(string[] args)
{
    Program p = new Program();
    p.Start();
    Console.ReadLine();
}

private void Start()
{
    System.Timers.Timer senderTimer;
    senderTimer = new System.Timers.Timer();
    senderTimer.Elapsed += new System.Timers.ElapsedEventHandler(SenderTimer);
    senderTimer.Interval = 500;
    senderTimer.Enabled = true;
}

private void SenderTimer(object Source, ElapsedEventArgs e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(Foo));
}

private void Foo(object state)
{
    string[] array = new string[] { "A", "2A", "3A", "4A", "5A", "6A", "7A", "8A", "9A", "10A" };

    for (int i = 0; i < array.Length; i++)
    {
        Trace.WriteLine("ID : " + Thread.CurrentThread.GetHashCode() + " --> " + array[i]);
        Thread.Sleep(1000); // Here I have a DB Operation, so i make it sleep
    }
}

我需要得到的结果是多个线程做同一件事是同步化的。 这是我必须得到的输出:希望我解释清楚。有没有办法做到这一点?

  • ID : 6 --> A
  • ID : 13 --> 2A
  • ID : 6 --> 3A
  • ID : 12 --> 4A
  • ID : 13 --> 5A
  • ID : 15 --> 6A
  • ID : 6 --> 7A
  • ID : 12 --> 8A
  • ID : 14 --> 9A
  • ID : 13 --> 10A

感谢任何帮助。非常感谢。

【问题讨论】:

  • 为什么要让多个线程同步工作?只使用一个线程,一切都很好。
  • @PVitt:可能是因为它的功课;-)

标签: c# multithreading asynchronous threadpool


【解决方案1】:

您应该在 Foo 函数之外打印数字数组。如果它在里面,每个线程都会尝试处理完整的列表,但这不是你想要的(据我所知)。

您想创建一个新函数,例如GetNextItemToProcess,它将返回数组中尚未处理的下一项。然后,在您的 Foo 函数中,调用类似

lock(this)
{
   string nextItem = GetNextItemToProcess();
   Trace.WriteLine("ID : " + Thread.CurrentThread.GetHashCode() + " --> " + nextItem );
}

由于每个线程都需要确保正确抓取下一个项目,因此您需要锁定。重要说明:锁定整个函数,同时确保你想要什么,不利于多线程。使用这种方法,它也可能是串行的。如果每项工作都可以按任意顺序执行,那么线程确实会给您带来好处,而这里的情况并非如此。如果你真的需要输出来“A,2A,3A”你最好连续做。如果它可以是“2A、A、3A”或随机顺序,其中每个项目预计只出现一次,那么线程就是你想要的。

【讨论】:

  • 这样,一个线程只能在一个foreach中工作。假设 DataTable 结果有 3 行,我在 dataTable 中循环,然后线程逐行工作。 3个线程可以在数据表中同时工作并且每个线程都在不同的行上工作吗??
  • 一般来说他们可以,但是你的原始帖子暗示他们需要按顺序输出,所以为了保证这一点,线程并没有真正的帮助。作为替代方案,您可以不锁定任何内容,但让每个工作项将其结果写入列表。然后,当所有线程都完成后,按排序顺序输出列表。这样,您就可以从仍然排序的结果中获得线程的好处。
【解决方案2】:

如果您想强制处理顺序,那么将其设为多线程是没有意义的,因为无论如何每个线程都会等待前一个线程。

如果您想并行进行处理,然后将结果按照收到的顺序排列,那么您可以使用

        string[] array = new string[] { "A", "2A", "3A", "4A", "5A", "6A", "7A", "8A", "9A", "10A" };
        var results = array.AsParallel().Select((item, i) =>
        new
        {
            Index = i,
            Result = ProcessItem(item)
        })
        .OrderBy(x => x.Index)
        .Select(i=>i.Result)
        .ToList();

【讨论】:

  • 我相信这是当前版本的 C# 和 .NET 框架中最简单的方法。
猜你喜欢
  • 1970-01-01
  • 2020-09-12
  • 1970-01-01
  • 2015-06-09
  • 2010-10-14
  • 1970-01-01
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
相关资源
最近更新 更多