【问题标题】:WinForms - Enable button on AsyncCallback from a separate threadWinForms - 从单独的线程启用 AsyncCallback 上的按钮
【发布时间】:2015-04-22 13:03:18
【问题描述】:

我对多线程非常陌生,因此,我确信我的整个问题很可能是错误的,但这更多的是让我了解事情如何正确完成,所以我希望你能原谅和任何解释设置为“白痴”级别将不胜感激!!!!

假设我的 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 线程)

然后,当异步进程完成时:

  1. Test 类中运行AsyncComplete 方法
  2. 重新启用表单上的按钮(Form 类中可能还有其他一些东西)

正如我所说,这对我来说是全新的。我想象的可以做的是在表单上创建一个 AsyncCallback 委托并将其传递给我的类(作为属性??)并让 AsyncComplete 方法在最后运行它,但似乎可以是非常糟糕的编程。

最好/正确的方法是什么 - 请理解我是这类东西的主要新手,所以我非常感谢任何链接/解释,以便了解多线程的正确方法像这样的场景。

此外,虽然这是用 C# 编写的,但我对 VB 和 C# 也同样熟悉,因此我们将不胜感激任何答案。

谢谢!!!

【问题讨论】:

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


    【解决方案1】:

    我建议您使用 TPL 而不是过时的 APM 方法,除非您的要求是使用旧的 .Net 框架版本。但回到问题。大多数 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());
    }
    

    【讨论】:

    • 非常感谢,nikis,我唯一的挑战是我无法控制返回IAsyncResult / 的foo() 方法将AsyncCallback 作为参数。在这种情况下,TPL 还能工作吗?
    • @JohnBus​​tos 是的,你可以从APM 创建任务,看看我的编辑
    • 非常感谢,尼基斯! - 我现在正在研究如何实现它,但这确实有道理!
    • SOO 抱歉,但这仍然留下了我的主要问题 - 在我的表单类中,我正在运行存在于单独类中的 RunOnSeparateThread 方法 - 该方法调用 foo() 和使用AsyncCallback 在该类中进行处置。我现在怎么在我的表格上也有一个AsyncCallback?这是主要问题....
    • 尼基斯...我明白了!!! - 我只是将public void RunOnSeparateThread() 更改为public IAsyncResult RunOnSeparateThread(),然后两者都做......谢谢!!!!
    猜你喜欢
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-08
    • 1970-01-01
    相关资源
    最近更新 更多