我的任务是处理下载排队系统,但我对从哪里开始感到困惑。
基本上我们需要做的就是拥有类似下载管理器的东西(但不是完全成熟)。我们有大约20-100个文件要下载,我们为用户提供一个UI(带有列表视图),以允许他们暂停,停止或移动一系列的工作。
我感到困惑的是要使用的数据结构,优先级队列似乎是从我的研究中得出的方式,但我对如何使其工作感到困惑。我是否有一个后台线程可以查看队列并获取下一个任务并继续前进?我需要在下载文件时提供进度 - 它们非常大,有时是120Mb(但是它本地,所以不超过10分钟)。
有时他们需要暂停工作,并将工作推到队列中,因为它被认为是紧急的。
它不是下载管理器,所以没有限制等问题。人们如何写这样的东西?
我想有一个像IDownloadTask这样的界面,它描述了要执行的任务,有一些属性和一个事件来公开它的进度(当任务运行时它会被连线)。
然后将IDownloadTask放入具有优先级的队列中。后台工作者选择它(我猜想PriorityQeue需要同步),然后在单独的线程上执行接口实现中的.Execute()方法。
听起来合理吗?有什么具体的例子,任何人都可以告诉我某个地方吗?
修改
哇谢谢你的回复和信任投票,我应该提到我使用的是.NET 2.0(由于Windows 9x的Windows兼容性要求,我们无法提升。)答案 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)
以下是两个可以用来帮助您入门的C#项目。
答案 2 :(得分:0)
以下是一个迷你实现,您可以从以下开始:
C# Threading issue with AutoResetEvent
您可能希望拥有更多的1个处理线程,并且您可能需要将一些通信添加回正在处理的数据中,以便您可以暂停等...