jmyns
jmyns

Reputation: 127

async/await UI object winforms

I am having some trouble understanding how to access UI object from my asynchronous method.

UI Before

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

Async Method Before

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);
            }
        });
    }

I have read that async/await does not allow to pass an object by reference. The navigate object is created on the main UI thread and is databound to controls on a form. I'd like to be able to have the object persist through threads but I don't know how to accomplish this or how else to approach this problem.

EDIT

Pass by value is in fact working as Stephen advised below. I found that my code was not setting the objects properties correctly... My implentation was all wrong. Instead of passing the object, I needed to just call a method on that object (such as n.IEcheckState()) and then access the properties with the "this" attribute.

UI After

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

Async Method After

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);
            }
        });
    }

Upvotes: 0

Views: 356

Answers (1)

Stephen Cleary
Stephen Cleary

Reputation: 456322

I have read that async/await does not allow to pass an object by reference.

It does not allow you to use ref. When you pass a value of reference type (e.g., IEcheckState's nav parameter), you are passing a reference by value. So you are sharing the same nav object between the caller and the callee.

Note the following best practices:

  • Avoid async void. Use async Task unless the compiler forces you to change it to async void.
  • Prefer Task.Run over Task.Factory.StartNew.

Upvotes: 1

Related Questions