mvp异步进度winforms

时间:2011-11-11 10:18:48

标签: c# winforms mvp

我实现了一个简单的ProgressPresenter

public interface IProgressView
{
    string Status { set; }
    void SetProgress(int percentageDone);

    void Display();
    void Close();

    event Action Closing;
}

class ProgressPresenter
{
    private IProgressView m_view;
    private ILongRunningTask m_task;
    private bool m_completed;

    public Progress(IProgressView view)
    {
        m_view = view;
    }

    public virtual void Display(ILongRunningTask task, string taskName)
    {
        m_task = task;

        m_view.Status = taskName " is running";

        m_view.Closing += OnClosing;
        task.ProgressChanged += UpdateProgress;
        task.Completed += Completed;

        task.StartAsync();

        m_view.Display();

        m_view.Closing -= OnClosing;
        task.ProgressChanged -= UpdateProgress;
        task.Completed -= Completed;
    }

    protected virtual void UpdateProgress(object sender, ProgessEventArgs e)
    {
        m_view.SetProgress(e.AlreadyDone * 100 / e.Total);
    }

    protected virtual void Completed()
    {
        m_completed = true;
        m_view.Status = "Completed";
        m_view.Close();
    }

    private virtual void OnClosing()
    {
        if (!m_completed) m_downloader.Cancel();
    }
}

我的问题是该任务在另一个线程中运行,并且每次调用该视图(实现为Form)都会抛出。我应该在表格中包装每个方法,如

public string Status
{
    set { Invoke(new Action(() => progressLabel.Text = value)); }
}

以防它可以从另一个线程调用?还是主持人有缺陷?

感谢任何建议

1 个答案:

答案 0 :(得分:2)

是的,你应该这样做。 我不知道您使用的是其他库,但为您的所有视图添加一个方面可能是一个好主意。

也许值得在基本视图中添加几个友好的方法;例如。我有这些:

    public void Invoke(Action action)
    {
        if (_control.InvokeRequired)
        {
            _control.Invoke(action);
            return;
        }

        action();
    }

    public T Invoke<T>(Func<T> action)
    {
        if (_control.InvokeRequired)
            return (T)_control.Invoke(action);

        return action();
    }

有关方面实施检查here

的示例