【问题标题】:async/await UI object winforms异步/等待 UI 对象 winforms
【发布时间】:2014-02-11 00:32:44
【问题描述】:

我在理解如何从我的异步方法访问 UI 对象时遇到了一些麻烦。

UI 之前

 private void btnNavigate_Click(object sender, EventArgs e)
    {
        Navigation n = new Navigation();
        n.Destination = cbQuickNav.Text;
        n.IEcheckState(n);
    }

之前的异步方法

public async void IEcheckState(Navigation nav)
    {
        Settings.AutoStartDialogWatcher = false;
        var ie = Browser.AttachTo<IE>(Find.ByTitle("TS"));
        bool success = false;

        await Task.Factory.StartNew(() =>
        {
            ie.GoTo("https://example.com");
            if (ie.ContainsText("Invalid login")) //Invalid login, please retry.
            {
                TSLogin(ie, nav);
            }
            else
            {
                quickNav(nav);
            }
        });
    }

我读到 async/await 不允许通过引用传递对象。导航对象在主 UI 线程上创建,并且数据绑定到表单上的控件。我希望能够让对象通过线程持续存在,但我不知道如何完成此操作或如何解决此问题。

编辑

按价值传递实际上正如斯蒂芬在下面建议的那样工作。我发现我的代码没有正确设置对象属性......我的实现都是错误的。我不需要传递对象,只需调用该对象的方法(例如 n.IEcheckState()),然后使用“this”属性访问属性。

用户界面之后

 private void btnNavigate_Click(object sender, EventArgs e)
    {
        Navigation n = new Navigation();
        n.Destination = cbQuickNav.Text;
        n.IEcheckState();
    }

之后的异步方法

public async Task IEcheckState()
    {
        Settings.AutoStartDialogWatcher = false;
        var ie = Browser.AttachTo<IE>(Find.ByTitle("TS"));
        bool success = false;

        await Task.Factory.StartNew(() =>
        {
            ie.GoTo("https://example.com");
            if (ie.ContainsText("Invalid login")) //Invalid login, please retry.
            {
                TSLogin(ie);
            }
            else
            {
                quickNav(this);
            }
        });
    }

【问题讨论】:

    标签: c# multithreading winforms asynchronous


    【解决方案1】:

    我读到 async/await 不允许通过引用传递对象。

    它不允许您使用ref。当您传递引用类型的值时(例如,IEcheckStatenav 参数),您是按值传递引用。因此,您在调用者和被调用者之间共享相同的 nav 对象。

    注意以下最佳做法:

    • 避免async void。使用async Task,除非编译器强制您将其更改为async void
    • 首选Task.Run 而不是Task.Factory.StartNew

    【讨论】:

    • 感谢斯蒂芬,your blog 非常有帮助。我正在运行 .Net 4.0,但似乎无法使用 Task.Run。你知道为什么会这样吗?
    • @jmyns:是的。我假设您使用的是Microsoft.Bcl.Async,并且对于该库,您必须使用TaskEx.Run 而不是Task.Run
    猜你喜欢
    • 2013-10-12
    • 1970-01-01
    • 1970-01-01
    • 2013-08-01
    • 2016-03-13
    • 2017-12-02
    • 2023-03-04
    • 2020-12-17
    • 1970-01-01
    相关资源
    最近更新 更多