课程提供进度信息的方式有哪些

时间:2011-11-17 21:36:44

标签: c#

我有多个类在线程中执行冗长的任务,并希望它们输出某种进度,所以我可以将它显示在进度条或计数器上。

我可以使用在接口中定义的事件或委托,但似乎每个实现我都需要编写完全相同的FireEvent代码来检查事件是否为null并提升它,如果不是的话。

使用抽象类似乎也很糟糕,因为这样的功能不属于最顶级的类,这意味着我必须再次在不同的地方实现它。

如何以最可重复使用的方式执行此操作,无需重复代码?

2 个答案:

答案 0 :(得分:6)

如果您对其他主题使用BackgroundWorker,则可以使用ReportProgress方法,这会引发ProgressChanged事件。

http://msdn.microsoft.com/en-us/library/cc221403%28v=vs.95%29.aspx

答案 1 :(得分:2)

我通常反转视图和模型之间的关系,以便视图了解模型。在此示例中,进度对话框将引用IProgress接口。然后它连接到ProgressChanged事件,因此视图可以在需要时自行更新。这样做的主要优点是各个类中的代码不会重复 - 只有那些告诉我们剩下多少内容的代码才在这些类中。通过这种方式,可以非常轻松地锁定经常发出进度状态的类的进度更新。

只是为了让你了解我通常做的事情:

interface IProgress
{
    event EventHandler ProgressChanged;
    int ProgressTarget { get; }
    int CurrentProgress { get; }
}

一个实施班。我甚至不知道它是否能够正常工作 - 这只是给人一种如何实现这个界面的印象。

class StreamCopier: IProgress
{
    private Stream _source;
    private Stream _destination;

    public StreamCopier(Stream source, Stream destination)
    {
        _source = source;
        _destination = destination;
    }

    public void WriteAll()
    {
        int b;
        while ((b = _source.ReadByte()) != -1)
        {
            _destination.WriteByte((byte)b);
            EventRaiser.Raise(ProgressChanged, this); // Just one call here! Can't be less
        }
    }

    public event EventHandler ProgressChanged;

    public int ProgressTarget {
        get { return (int)_source.Length; }
    }

    public int CurrentProgress {
        get { return (int)_destination.Position; }
    }
}

然后是EventRaiser课程。注意如何在参数堆栈上传递处理程序引用,因此不需要对'tmp'进行线程安全的复制! :)

static class EventRaiser
{
    public static void Raise(EventHandler handler, object sender, EventArgs args)
    {
        handler(sender, args);
    }

    public static void Raise(EventHandler handler, object sender)
    {
        Raise(handler, sender, EventArgs.Empty);
    }
}