1

I am trying to use Async and Await to enable a task only when a button disable event has completed.

I tried using:

   protected async void btnStart_Click(object sender, EventArgs e)
    {
        tskDisabled = DisableButton();
        int result = await tskDisabled;
        if (result == 1)
            FilesCount();
    }

    private async Task<int> DisableButton()
    {
        btnStart.Enabled = false;
        await Task.Delay(1000);
        return 1;
    }

I want to start the FilesCount() method only when the button btnStart is disabled.

At present, the task starts but button remains enabled.

svick
  • 236,525
  • 50
  • 385
  • 514
RKh
  • 13,818
  • 46
  • 152
  • 265
  • possible duplicate of [General purpose FromEvent method](http://stackoverflow.com/questions/12865848/general-purpose-fromevent-method) – i3arnon Nov 23 '14 at 07:39
  • 2
    Usually disabling a button is a cheap operation and `FilesCount` could probably be an operation to await on. If a button doesn't get disabled immediately, it means that a UI thread is busy doing something that should be done on another thread. – Ondrej Janacek Nov 23 '14 at 07:41
  • 1
    What you mean by `button disabled` event? I think you are in the wrong way. Why you try to asynchronously disable the button? Something long running? – Hamlet Hakobyan Nov 23 '14 at 07:44
  • Are you using WinForms? `btnStart.Enabled = false;` should complete synchronously. http://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/Control.cs,8007 Unless you're not on the UI thread, in which case ... stop that. – ta.speot.is Nov 23 '14 at 08:08
  • I am using ASP. NET Web Forms. Sorry, I should have mentioned it before. – RKh Nov 23 '14 at 08:09

4 Answers4

3

You are using WebForms. A WebForm is not "live". It is not connected to what the browser is showing. The purpose of all ASP.NET objects in a given request is simply to generate HTML once. After that they die.

All of what you are doing there happens before the HTML is even sent to the browser. This will never work.

You need a client-side solution for interactivity and logic-controlled content. Maybe you can use jQuery to manipulate the button. The UpdatePanel is also worth looking into.

usr
  • 168,620
  • 35
  • 240
  • 369
0

Maybe you are looking for something like this?

private async Task<int> FilesCountAsync()
{
    ....
}

protected async void btnStart_Click(object sender, EventArgs e)
{
    btnStart.Enabled = false;
    var fileCount = await FilesCountAsync();
    SetFileCountInUI(fileCount);
    btnStart.Enabled = true;
}
Hamlet Hakobyan
  • 32,965
  • 6
  • 52
  • 68
  • I tried this way as well, but the button remains enabled and it jumps to the FileCount method. – RKh Nov 23 '14 at 07:50
  • What are you mean? After the `btnStart.Enabled = false;` the `btnStart.Enabled` still remain `true`? – Hamlet Hakobyan Nov 23 '14 at 07:52
  • Even after btnStart.Enabled = false, the UI remains busy and does not disable button. The control immediately moves to the next statement that is FilesCount(). – RKh Nov 23 '14 at 07:54
  • As you see in the above the `FilesCountAsync` is awaitable. So UI can't be busy by `FilesCountAsync`. – Hamlet Hakobyan Nov 23 '14 at 07:55
  • Yes I have seen. I tried but the button remains enabled. The UI gets blocked once the Start button is clicked. Try it. – RKh Nov 23 '14 at 07:57
  • Ok. I figured out your problem. Your `FileCount` isn't awaitable. Try updated solution and make sure that your `FileCount` is awaitable. – Hamlet Hakobyan Nov 23 '14 at 08:00
  • Thanks, I will try this. However I have issues with the btnStart button. FilesCount will run in async I agree, but before FilesCount start, the button disable event should get completed. – RKh Nov 23 '14 at 08:06
  • I am using Web Forms. – RKh Nov 23 '14 at 08:10
  • I not familiar with `Web Forms` but I think it doesn't matter. The `SynchronizationContext` of the `ASP.NET` also track the approaches. It will be more helpful if you provide the `FilesCount` implementation. – Hamlet Hakobyan Nov 23 '14 at 08:14
  • Isn't the problem that in Web Forms `btnStart_Click` will execute on the server, and then update the page's state later? So `btnStart.Enabled = false` will do nothing until the whole request is processed by the server and the result returned to the client. At which point it's `Enabled = true` again. – ta.speot.is Nov 23 '14 at 08:37
0

How about some javascript on the client ? Add js function to your markup inside script tags:

function disableMe(id) {
    if (id != undefined)
        if (document.getElementById(id.id) != null)
            document.getElementById(id.id).setAttribute("disabled", "disabled");
}

Next add OnClientClick to btnStart (note return true):

<asp:Button runat="server" ID="btnStart" OnClientClick="return disableMe(this);return true;" />
Jeff Mergler
  • 1,384
  • 20
  • 27
0

btnStart.Enabled = false; will effect at the UI only after the response is received to the client. So as usr and jeffreymergler said it needs a client side solution.

But added to that it needs a response/ error handling logic as well. That means a javascript code disable the button, but once response received it needs to be re-enabled or whatever. That is being said a client side logic with ajax to call the server, do the process and in the callback handle the response or error appropriate. Update Panel is one of the control which provides the ajax support and have events for handling. If update panel not sufficient then go with a custom logic.