WinForms - 从单独的线程

时间:2015-04-22 13:03:19

标签: c# .net vb.net multithreading asynchronous

我对多线程非常陌生,因此,我确信我的整个问题很可能是错的,但这对我来说更适合学习如何正确完成,所以我希望你能做到这一点。 ;请原谅和任何解释设置在"白痴"水平将非常感谢!!!!

假设我的WinForm外部有以下类:

public class test
{
    public void RunOnSeparateThread()
    {
        // Some function that takes an AsyncCallback as a parameter and runs Asynchronously
        // Returns IAsyncResult
        foo(m_asyncCallback);
    }

    private AsyncCallback m_asyncCallback = new AsyncCallback(AsyncComplete);
    private static void AsyncComplete(IAsyncResult result)
    { 
        // Whatever disposal stuff needs to be done, etc.
    }
}

现在,我想要做的是在我的winform上有一个按钮,当按下时:

  1. 禁用按钮
  2. 在单独的线程上运行RunOnSeparateThread进程(不占用GUI线程)
  3. 然后,当异步过程完成时:

    1. AsyncComplete
    2. 中运行Test方法
    3. 重新启用表单上的按钮(也可能是Form类中的其他一些内容)
    4. 正如我所说,这对我来说都是全新的。我想象的可能是在表单上创建一个AsyncCallback委托并将其传递给我的类(作为属性??)并在最后运行AsyncComplete方法,但它看起来这可能是非常糟糕的编程。

      这样做的最佳/正确方法是什么 - 请理解我是这类东西的主要新手,所以我非常感谢任何链接/解释,以便了解正确的多方式-thread用于此类场景。

      此外,虽然这是用C#编写的,但我在VB和C#中也同样适用,所以任何答案都会非常感激。

      感谢!!!

1 个答案:

答案 0 :(得分:2)

除非您的要求是使用旧的.Net框架版本,否则我建议您使用TPL而不是过时的APM方法。但回到这个问题。大多数UI框架不允许从非主(非UI)线程进行UI修改。因此,您应该使用Invoke方法将更新发布到UI线程循环(或BeginInvoke以异步方式执行委托)。使用TPL一切都非常简单:

void button_Click(object sender, EventArgs e)
{
    button.Enabled = false;
    Task.Factory.StartNew(() =>
    {
        //long-running stuff
    }).ContinueWith((result) =>
    {
        button.Enabled = true;
    }, TaskScheduler.FromCurrentSynchronizationContext());
}

请注意,您提出的问题实际上过于宽泛,最好在WinForms中以异步方式阅读有关执行任务的文章。

修改

如果您无法控制foo,则代码可能如下所示:

void button_Click(object sender, EventArgs e)
{
    button.Enabled = false;
    IAsyncResult asyncResult = foo(...);
    Task.Factory.FromAsync(asyncResult, (result) =>
    {
        button.Enabled = true;
    }, TaskCreationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}