从C#中主线程的辅助线程运行Method?

时间:2015-02-03 23:23:40

标签: c# multithreading progress-bar vsto threadpool

我正在使用VSTO,我想通过COM Interop为Excel模型(获取和设置rages)操作的任务设置进度条。在执行任何在Excel模型上运行的任务时,强烈建议仅从主线程执行此操作(有很多帖子可以讨论这个问题)。

我的问题是我希望有一个进度条(存在于辅助线程上),我希望能够在进度条加载时启动我的任务(在主线程上)。是否有某种方法可以将函数排入队列以从辅助线程执行主线程?如果没有,还有其他方法可以设置吗?

我的来源如下:

abstract class BaseProgressTask
{
    private ProgressForm _form;
    public volatile bool CancelPending;

    private void ShowProgressForm()
    {
        _form = new ProgressForm(this) { StartPosition = FormStartPosition.CenterScreen };
        _form.ShowDialog();
    }

    public BaseProgressTask()
    {
        ThreadStart startDelegate = ShowProgressForm;
        Thread thread = new Thread(startDelegate) { Priority = ThreadPriority.Highest };
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
    }

    public abstract void Run();

    protected void ReportProgress(int percent)
    {
        _form.BeginInvoke(new Action(() => _form.SetProgress(percent)));
    }

    protected void CloseForm()
    {
        _form.BeginInvoke(new Action(() => _form.Close()));
    }
}

public partial class ProgressForm : Form
{
    private BaseProgressTask _task;
    public ProgressForm(BaseProgressTask task)
    {
        InitializeComponent();
        _task = task;
    }

    private void btnCancel_Click(object sender, EventArgs e)
    {
        _task.CancelPending = true;
        lblStatus.Text = "Cancelling...";
    }

    public void SetProgress(int percent)
    {
        myProgressBar.Value = percent;
    }

    private void ProgressForm_Load(object sender, EventArgs e)
    {
        //Any way to do this?
        ExecuteOnMainThread(_task.Run);
    }
}

1 个答案:

答案 0 :(得分:1)

您可以考虑使用BackgroundWorker组件。它在单独的线程上执行操作,并允许使用事件处理程序以更方便的方式报告进度。有关详细信息,请参阅How to: Use a Background WorkerWalkthrough: Multithreading with the BackgroundWorker Component (C# and Visual Basic)

Windows API中的SendMessage函数可用于在主线程上运行操作。

如果您的主线程是表单,您可以使用以下简短代码处理它:

 if (InvokeRequired)
 {
     this.Invoke(new Action(() => MyFunction()));
     return;
 }

或.NET 2.0

 this.Invoke((MethodInvoker) delegate {MyFunction();});