C# 并行线程和控制?

C# 并行线程和控制?,c#,winforms,multithreading,.net-4.0,thread-safety,C#,Winforms,Multithreading,.net 4.0,Thread Safety,我有这样一个函数: private void GetRSS(int start, int end) { for (int i = start; i < end; i++) { string content = string.Empty; using (WebClient client = new WebClient()) { //some code here get html content

我有这样一个函数:

private void GetRSS(int start, int end)
{
    for (int i = start; i < end; i++)
    {
        string content = string.Empty;
        using (WebClient client = new WebClient())
        {
            //some code here get html content
        }
        // some code here parse content
    }
}
然后我启动控制器,从控制器内部调用每个线程来执行上面的函数,并从控制器跟踪每个线程,比如:

private void _ControlerStart()
{
    _worker1 = new Thread(GetRSS);
    try
    {
        _worker1.Start(1, 7711);
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.ToString());
    }
    // repeat the above to all the 4 threads
    _isRunning = true;
    while (_isRunning)
    {
        if (_worker1.ThreadState != ThreadState.Running && _worker2.ThreadState != ThreadState.Running && _worker3.ThreadState != ThreadState.Running && _worker4.ThreadState != ThreadState.Running)
            _isRunning = false;
    }
    MessageBox.Show("Done");
}
当我想到上面这些乱七八糟的事情时,我意识到这不是做我想做的事情的最佳方式,而我就在这里;)


我如何管理多个线程来运行同一个函数,并且能够知道每个线程何时结束工作,以关闭、保存或合并数据,或者执行主线程中剩下的任何操作?

是否有不使用TPL的特定原因

正如您可能已经注意到的,提供的代码的问题在于它不是声明性的。你是在告诉机器怎么做,而不是你想做什么

在我的评论中,我建议使用

在OP的评论中,我看到

我有30k个页面要检索,每个页面上有10条记录,所以我想将30k个页面分成4个线程,在下载到字符串中后,每个页面都需要解析

第一部分定义了要执行的操作,第二部分清楚地描述了为PC牵手。我的建议是停止握住PC的手,并考虑要执行的高级操作

  • 索取N页
  • 当任何一个页面可用时,使用结果
  • 当所有N个页面都可用并已使用时,整理该结果
  • 这需要异步编程。在.NET4.0中,它主要在F#2.0下提供。C#4.0可以将APM与continuations一起使用,但我不推荐它


    C#vNext对此有支持,请参见VS 2012。

    是否有不使用第三方物流的具体原因

    private static void GetRSS(int start, int end)
    {
        var bunchSize = (end - start) / 4 + 1;
    
        var threads = new List<Thread>();
    
        for (int i = 0; i < 4; i++)
        {
            var currStart = start + i * bunchSize;
            var currEnd = currStart + bunchSize;
    
            if (currEnd > end)
            {
                currEnd = end;
            }
    
            var thread = new Thread(() =>
                                        {
                                            // thread logic using currStart and currEnd
    
                                            string content = string.Empty;
                                            using (WebClient client = new WebClient())
                                            {
                                                //some code here get html content
                                            }
                                            // some code here parse content
                                        });
    
            threads.Add(thread);
            thread.Start();
        }
    
        foreach (var thread in threads)
        {
            thread.Join();
        }
    }
    
    正如您可能已经注意到的,提供的代码的问题在于它不是声明性的。你是在告诉机器怎么做,而不是你想做什么

    在我的评论中,我建议使用

    在OP的评论中,我看到

    我有30k个页面要检索,每个页面上有10条记录,所以我想将30k个页面分成4个线程,在下载到字符串中后,每个页面都需要解析

    第一部分定义了要执行的操作,第二部分清楚地描述了为PC牵手。我的建议是停止握住PC的手,并考虑要执行的高级操作

  • 索取N页
  • 当任何一个页面可用时,使用结果
  • 当所有N个页面都可用并已使用时,整理该结果
  • 这需要异步编程。在.NET4.0中,它主要在F#2.0下提供。C#4.0可以将APM与continuations一起使用,但我不推荐它

    C#vNext对此有支持,请参见VS 2012。

    私有静态void GetRSS(int start,int end)
    
    private static void GetRSS(int start, int end)
    {
        var bunchSize = (end - start) / 4 + 1;
    
        var threads = new List<Thread>();
    
        for (int i = 0; i < 4; i++)
        {
            var currStart = start + i * bunchSize;
            var currEnd = currStart + bunchSize;
    
            if (currEnd > end)
            {
                currEnd = end;
            }
    
            var thread = new Thread(() =>
                                        {
                                            // thread logic using currStart and currEnd
    
                                            string content = string.Empty;
                                            using (WebClient client = new WebClient())
                                            {
                                                //some code here get html content
                                            }
                                            // some code here parse content
                                        });
    
            threads.Add(thread);
            thread.Start();
        }
    
        foreach (var thread in threads)
        {
            thread.Join();
        }
    }
    
    { var bunchSize=(结束-开始)/4+1; var threads=newlist(); 对于(int i=0;i<4;i++) { var currStart=start+i*束化; var currEnd=currStart+bunchize; 如果(当前结束>结束) { currEnd=结束; } 变量线程=新线程(()=> { //使用currStart和currEnd的线程逻辑 string content=string.Empty; 使用(WebClient=newWebClient()) { //这里的一些代码获取html内容 } //这里的一些代码解析内容 }); 线程。添加(线程); thread.Start(); } foreach(线程中的var线程) { thread.Join(); } }
    私有静态void GetRSS(int start,int end)
    {
    var bunchSize=(结束-开始)/4+1;
    var threads=newlist();
    对于(int i=0;i<4;i++)
    {
    var currStart=start+i*束化;
    var currEnd=currStart+bunchize;
    如果(当前结束>结束)
    {
    currEnd=结束;
    }
    变量线程=新线程(()=>
    {
    //使用currStart和currEnd的线程逻辑
    string content=string.Empty;
    使用(WebClient=newWebClient())
    {
    //这里的一些代码获取html内容
    }
    //这里的一些代码解析内容
    });
    线程。添加(线程);
    thread.Start();
    }
    foreach(线程中的var线程)
    {
    thread.Join();
    }
    }
    
    在任务方式中,您可以使用在所有任务完成后执行某些操作

        private void ButtonOnClick(object sender, RoutedEventArgs routedEventArgs) {
            const int n = 15;
            var tasks = new Task<int>[n];
            for (int i = 0; i < n; i++) {
                tasks[i] = Task.Factory.StartNew(
                    () => {
                        Thread.Sleep(500);
                        return 100;
                    });
            }
    
            Task.Factory.ContinueWhenAll(
                tasks,
                ts => { text.Text = string.Format("Sum: {0}", ts.Sum(task => task.Result)); },
                CancellationToken.None,
                TaskContinuationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext());
        }
    
    private void按钮非点击(对象发送者,RoutedEventArgs RoutedEventArgs){
    常数int n=15;
    var tasks=新任务[n];
    对于(int i=0;i {
    睡眠(500);
    返回100;
    });
    }
    Task.Factory.continuewhalll(
    任务,
    ts=>{text.text=string.Format(“Sum:{0}”,ts.Sum(task=>task.Result));},
    取消令牌。无,
    TaskContinuationOptions。无,
    TaskScheduler.FromCurrentSynchronizationContext());
    }
    
    这里我用的是 在UI线程中执行延续任务。

    在任务方式中,您可以使用在所有任务完成后执行某些操作

        private void ButtonOnClick(object sender, RoutedEventArgs routedEventArgs) {
            const int n = 15;
            var tasks = new Task<int>[n];
            for (int i = 0; i < n; i++) {
                tasks[i] = Task.Factory.StartNew(
                    () => {
                        Thread.Sleep(500);
                        return 100;
                    });
            }
    
            Task.Factory.ContinueWhenAll(
                tasks,
                ts => { text.Text = string.Format("Sum: {0}", ts.Sum(task => task.Result)); },
                CancellationToken.None,
                TaskContinuationOptions.None,
                TaskScheduler.FromCurrentSynchronizationContext());
        }
    
    private void按钮非点击(对象发送者,RoutedEventArgs RoutedEventArgs){
    常数int n=15;
    var tasks=新任务[n];
    对于(int i=0;i