Task.ConfigureAwait behavior after UI interception

I played with Task.ConfigureAwaitto better understand what is happening behind the hood. So I got this weird behavior by combining some UI access controls with ConfigureAwait.

The following is an example application using a simple window form with 1 Buttonfollowed by the test results:

private async void btnDoWork_Click(object sender, EventArgs e)
{
    List<int> Results = await SomeLongRunningMethodAsync().ConfigureAwait(false);

    int retry = 0;
    while(retry < RETRY_COUNT)
    {
        try
        {
            // commented on test #1 & #3 and not in test #2
            //if(retry == 0)
                //throw new InvalidOperationException("Manually thrown Exception");

            btnDoWork.Text = "Async Work Done";
            Logger.Log("Control Text Changed", logDestination);
            return;
        }
        catch(InvalidOperationException ex)
        {
            Logger.Log(ex.Message, logDestination);
        }

        retry++;
    }
}

Now after clicking the button:

Test 1 Search Results: (exactly like the code above)

1. Cross-thread operation not valid: Control 'btnDoWork' accessed from a thread other than the thread it was created on.
2. Control Text Changed

Testing 2 Log results: (manual exception error without commenting)

1.  Manually thrown Exception
2.  Cross-thread operation not valid: Control 'btnDoWork' accessed from a thread other than the thread it was created on.
3.  Control Text Changed

Test 3 Log Results: (Same as 1, but without debugger)

1. Control Text Changed

So the questions are:

  • (Cross-Thread ) Main ?

  • ?

  • ( exe) ?

+4
1

, , , .

Button.Text:

  set
  {
    if (value == null)
      value = "";
    if (value == this.Text)
      return;
    if (this.CacheTextInternal)
      this.text = value;
    this.WindowText = value;
    this.OnTextChanged(EventArgs.Empty);
    if (!this.IsMnemonicsListenerAxSourced)
      return;
    for (Control control = this; control != null; control = control.ParentInternal)
    {
      Control.ActiveXImpl activeXimpl = (Control.ActiveXImpl) control.Properties.GetObject(Control.PropActiveXImpl);
      if (activeXimpl != null)
      {
        activeXimpl.UpdateAccelTable();
        break;
      }
    }
  }

, , this.WindowText = value; ( Handle ). , text - :

if (this.CacheTextInternal)
   this.text = value;

, , , (, , ). - , .

, , , :

if (value == this.Text)
  return;

, , , .

+3

All Articles