4

这是我第一次在 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(site,i); 我++;// 柜台 }

因为我是初学者,所以我有几个问题。

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

3 回答 3

2

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

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

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

于 2013-04-06T12:08:27.997 回答
1

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

另请参阅: 并行编程模式:使用 .NET Framework 4 理解和应用并行模式

于 2013-04-06T12:14:32.000 回答
1

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

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

4)Thread 类很好,因为您可以根据您的要求使用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();
}

代码未测试

于 2013-04-06T12:26:14.870 回答