如何在这种多线程情况下编写简洁的代码?

问题描述 投票:0回答:2

此代码效果不错,但看起来很糟糕。如何在这种情况下编写漂亮的代码?

您可以在操场上看它:https://dotnetfiddle.net/GUZni0

或下面的代码:

using System;
using System.Collections.Generic;
using System.Threading;

public class Program
{
    static object valueLocker = new Object();
    static List<int> uidList;
    static int takeuid = -1;
    static int countThreads = 0;
    public static void Main()
    {
        for (;;) { 
        Console.WriteLine("Hello World");

        uidList = new List<int>();
        uidList.Add(0);
        uidList.Add(1);
        uidList.Add(2);
        uidList.Add(3);
        uidList.Add(4);
        countThreads = 0;
        for (int i = 0; i < 10; i++)
        {
            Thread thread = new Thread(TakeUidThread);
            thread.Start();
        }

线程完成后每0.5秒检查主线程并获取新的uidList

        while (countThreads < 10)
        {
            Thread.Sleep(500);
        }
        Console.WriteLine("All threads finished");

        }
    }

    public static void TakeUidThread() 
    {
        var localuid = -1;

            while (localuid < uidList.Count)
            {
                // thread takes free uid
                lock (valueLocker)
                {
                    takeuid++;
                    localuid = takeuid;
                }

                if (localuid < uidList.Count && localuid != -1)
                {
                    DoSomeJob(uidList[localuid]);
                }

            }

Thread inc countThreads结尾

            lock (valueLocker)
            {
                countThreads++;
            }
    }
    private static void DoSomeJob(int uid)
    {

    }
}
c# multithreading
2个回答
0
投票

嗯,您可以尝试使用PLinqParallel Linq),并摆脱lock s,Thread s等

  using System.Linq;

  ...

  uidList
    .AsParallel()
    //.WithMergeOptions(ParallelMergeOptions.NotBuffered)
    //.AsOrdered()
    .ForAll(item => DoSomeJob(item));

0
投票

这是使用线程的非常糟糕的方法。启动线程真的很繁琐,当执行一些硬核计算时,它被认为是一个很好的解决方案。在多线程环境中工作时,您需要在两个目标之间进行选择:

  • 您为性能而做:您实际上做了很多CPU工作,其中包括一些算法上的复杂性,其他方法无法降低]
  • 您为输入/输出(I / O)执行此操作
  • :为许多客户端提供服务,大多数情况下,您等待来自其他端点(例如SQL Server,硬盘驱动器,网络接口或某些其他系统)的结果组件。

    为了提高性能,请执行以下操作:

Parallel.ForEach(uidList, DoSomeJob);

这将创建重量级的Thread,并且在某个时间点几乎会使用您的全部CPU功能。

对于I / O,请执行以下操作:

private async Task DoSomeJob(int uid){ ... }

await Task.WhenAll(uidList.Select(DoSomeJob));

这将需要开发async样式,但是Task是非常轻量的对象,并且您几乎看不到CPU达到1%,因为预计大多数情况下您的任务只是等待某事而已发生,然后发生其他事情,然后所有这些……等等。

© www.soinside.com 2019 - 2024. All rights reserved.