C#中的多线程队列

时间:2009-08-25 01:44:38

标签: c# data-structures multithreading queue cpu

我的任务是处理下载排队系统,但我对从哪里开始感到困惑。

基本上我们需要做的就是拥有类似下载管理器的东西(但不是完全成熟)。我们有大约20-100个文件要下载,我们为用户提供一个UI(带有列表视图),以允许他们暂停,停止或移动一系列的工作。

我感到困惑的是要使用的数据结构,优先级队列似乎是从我的研究中得出的方式,但我对如何使其工作感到困惑。我是否有一个后台线程可以查看队列并获取下一个任务并继续前进?我需要在下载文件时提供进度 - 它们非常大,有时是120Mb(但是它本地,所以不超过10分钟)。

有时他们需要暂停工作,并将工作推到队列中,因为它被认为是紧急的。

它不是下载管理器,所以没有限制等问题。人们如何写这样的东西?

我想有一个像IDownloadTask这样的界面,它描述了要执行的任务,有一些属性和一个事件来公开它的进度(当任务运行时它会被连线)。

然后将IDownloadTask放入具有优先级的队列中。后台工作者选择它(我猜想PriorityQeue需要同步),然后在单独的线程上执行接口实现中的.Execute()方法。

听起来合理吗?有什么具体的例子,任何人都可以告诉我某个地方吗?

修改

哇谢谢你的回复和信任投票,我应该提到我使用的是.NET 2.0(由于Windows 9x的Windows兼容性要求,我们无法提升。)

3 个答案:

答案 0 :(得分:2)

对于跟踪进度,您的线程可以使用事件报告进度以及完成。以下是完成事件的示例,但相同的概念适用于状态更新事件。您只需更改保存数据的类,以便它可以传递有关进度的信息。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace ThreadWithDataReturnExample
{
    public partial class Form1 : Form
    {
        private Thread thread1 = null;

        public Form1()
        {
            InitializeComponent();

            thread1 = new Thread(new ThreadStart(this.threadEntryPoint));
            Thread1Completed += new AsyncCompletedEventHandler(thread1_Thread1Completed);
        }

        private void startButton_Click(object sender, EventArgs e)
        {
            thread1.Start();
            //Alternatively, you could pass some object
            //in such as Start(someObject);
            //With apprioriate locking, or protocol where
            //no other threads access the object until
            //an event signals when the thread is complete,
            //any other class with a reference to the object 
            //would be able to access that data.
            //But instead, I'm going to use AsyncCompletedEventArgs 
            //in an event that signals completion
        }

        void thread1_Thread1Completed(object sender, AsyncCompletedEventArgs e)
        {
            if (this.InvokeRequired)
            {//marshal the call if we are not on the GUI thread                
                BeginInvoke(new AsyncCompletedEventHandler(thread1_Thread1Completed),
                  new object[] { sender, e });
            }
            else
            {
                //display error if error occurred
                //if no error occurred, process data
                if (e.Error == null)
                {//then success

                    MessageBox.Show("Worker thread completed successfully");
                    DataYouWantToReturn someData = e.UserState as DataYouWantToReturn;
                    MessageBox.Show("Your data my lord: " + someData.someProperty);

                }
                else//error
                {
                    MessageBox.Show("The following error occurred:" + Environment.NewLine + e.Error.ToString());
                }
            }
        }

        #region I would actually move all of this into it's own class
            private void threadEntryPoint()
            {
                //do a bunch of stuff

                //when you are done:
                //initialize object with data that you want to return
                DataYouWantToReturn dataYouWantToReturn = new DataYouWantToReturn();
                dataYouWantToReturn.someProperty = "more data";

                //signal completion by firing an event
                OnThread1Completed(new AsyncCompletedEventArgs(null, false, dataYouWantToReturn));
            }

            /// <summary>
            /// Occurs when processing has finished or an error occurred.
            /// </summary>
            public event AsyncCompletedEventHandler Thread1Completed;
            protected virtual void OnThread1Completed(AsyncCompletedEventArgs e)
            {
                //copy locally
                AsyncCompletedEventHandler handler = Thread1Completed;
                if (handler != null)
                {
                    handler(this, e);
                }
            }
        #endregion

    }
}

答案 1 :(得分:1)

答案 2 :(得分:0)

以下是一个迷你实现,您可以从以下开始:

C# Threading issue with AutoResetEvent

您可能希望拥有更多的1个处理线程,并且您可能需要将一些通信添加回正在处理的数据中,以便您可以暂停等...