我实现了一个简单的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)); }
}
以防它可以从另一个线程调用?还是主持人有缺陷?
感谢任何建议
答案 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
的示例