2011-11-11 50 views
1

我实现了一个简单的ProgressPresenterMVP异步进步的WinForms

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)); } 
} 

以防万一它可以从另一个线程中调用?或者Presenter有缺陷?

任何建议表示赞赏

回答

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

+0

THX的答案的一个例子。这两个选项都非常有用。 ATM我不想要一个真正的国际奥委会依赖,所以我推出了我自己的非常简单,因此我在第二个选项现在 – Firo

+0

您可以使用Postharp作为代理类方面的替代! –