2011-11-11 117 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作爲代理類方面的替代! –