C#线程问题&最佳做法

时间:2013-04-06 11:56:37

标签: c# multithreading

这是我第一次在C#应用程序中使用线程。基本上它是一个应用程序,它检查列表中的一堆网站,无论它是死还是活。

这是我第一次尝试使用多线程

    public void StartThread(string URL,int no)
    {
        Thread newThread = new Thread(() =>
        {
            BeginInvoke(new Action(() => richTextBox1.Text += "Thread " + no + " Running" + Environment.NewLine));
            bool b = ping(URL);
            if (b == true) { BeginInvoke(new Action(() => richTextBox2.Text += "Okay" + Environment.NewLine)); }
            else
            { return; }
        });

        newThread.Start();
    }

我正在使用上面的函数来创建新线程,并且每个线程都是在循环内创建的。

  

foreach(网站中的字符串网站){       StartThread(站点,I);       我++; //柜台}

由于我是初学者,我几乎没有问题。

  1. 代码工作正常,但我不确定这是否是最佳解决方案
  2. 有时线程运行得很好但有时Threads不会从方法 ping()返回任何值,它会检查主机,如果在线使用WebRequest则返回true。通常吗?
  3. 如果我要求用户指定他需要使用的线程数,我怎样才能在这些线程中平均分配工作?
  4. 他们是一个优雅的方式,我跟踪线程的状态,(死/活)?我目前使用rocess.GetCurrentProcess().Threads.Count;

3 个答案:

答案 0 :(得分:1)

为每个请求启动一个新线程是低效的......你可能希望拥有固定数量的工作线程(因此可以在cpu的每个核心上运行)

查看ConcurrentQueue<T>类,它将为您提供一个线程安全的先进先出队列,您可以在其中排队您的请求并让每个工作线程将请求出列,处理它,等等直到队列为空......

请注意,您不能从主GUI线程之外的其他线程调用GUI上的控件...查看ISynchronizeInvoke接口,它可以帮助您确定是否需要处理跨线程情况通过调用另一个线程

答案 1 :(得分:1)

您应该考虑the .Net ThreadPool。但是,它通常不适合执行时间超过大约秒的线程。

另见: Patterns for Parallel Programming: Understanding and Applying Parallel Patterns with the .NET Framework 4

答案 2 :(得分:1)

1)您的解决方案没问题。 Thread类已被Task类部分取代,如果您正在编写新代码,则可以使用它。 .NET 4.5中还有一些全新的东西,名为await。但是,请参阅4)。

2)如果网站已经死亡,您的ping方法可能会崩溃。您可以向我们展示该方法的代码。

4)线程类很好,因为您可以根据您的要求使用ThreadState属性轻松检查线程状态 - 只需创建一个List<Thread>,将您的线程放入其中,然后启动他们一个接一个。

3)如果要从输入加载线程数并均匀分配工作,请将任务放入队列中(可以使用已经建议的ConcurrentQueue)并让线程从队列中加载URL 。示例代码:

你初始化一切

void initialize(){
ConcurrentQueue<string> queue = new ConcurrentQueue<string>();
foreach(string url in websites)
{
    queue.Enqueue(url);
}
//and the threads
List<Thread> threads = new List<Thread>();
for (int i = 0; i < threadCountFromTheUser; i++)
{
    threads.Add(new Thread(work));
}}

//work method
void work()
{
    while (!queue.IsEmpty)
    {
        string url;
        bool fetchedUrl = queue.TryDequeue(out url);
        if (fetchedUrl)
            ping(url);
    }
}

然后运行

foreach (Thread t in threads)
{
    t.Start();
}

代码未经过测试