0

I have a form, like below, that accepts a Task<T>, waits for completion and then returns after await by closing the form:

public partial class SomeForm<T> : Form
{
    public T ReturnValue { get; private set; }
    private Task<T> Task { get; set; }

    public SomeForm(string waitingText, Task<T> task)
    {
        InitializeComponent();

        ...

        PerformTask();
    }

    private async void PerformTask()
    {
        ReturnValue = await Task;
        this.Close();
    }
}

However, whilst this method runs happily, it gets to ReturnValue = await Task; and then does not go any further. The method will run normally without being sent to the method and does not delay. I have a feeling it's to do with how I'm using async and await, but I'm new to TPL etc.

Please help me identify what's wrong with the above script, and in identifying why it never returns.

Edit: TaskA was a typo. Here's the Task's method; ImportedFunctions. BS_Robots_LoadDrive(..) is a DllImport of a C++ function, which works just fine synchronously, even on another thread (like in the final snippet), but not with an async paramter.

    public uint LoadDisc()
    {
        uint response = ImportedFunctions.BS_Robots_LoadDrive(DriveLetters[0],
                        (int)BSRobotConstants.BIN_ID_DEFAULT,
                        (int)BSRobotConstants.POSITION_TYPE_INPUTBIN,
                        0);

        switch (response)
        {
            case BSRobotConstants.OK:
            case BSRobotConstants.OK_WITH_MESSAGE:
            case BSRobotConstants.FROMTRAY_NO_DISC:
            case BSRobotConstants.INVALID_DRIVE:
            case BSRobotConstants.INVALID_POSITION:
            case BSRobotConstants.TOTRAY_NO_DISC:
            case BSRobotConstants.TOTRAY_NOT_OPEN:
            case BSRobotConstants.FATAL_ERROR:
                break; 
            case BSRobotConstants.BUSY:

                break;
            case BSRobotConstants.TOTRAY_HAS_DISC:
                RejectDisc();
                response = LoadDisc();
                break;
        }

        return response;
    }

This works:

private async void PerformTask()
{
    Task.Start();
    Task.Wait();

    ReturnValue = Task.Result;
    DialogResult = DialogResult.OK;
}

But the first code snippet doesn't.

Nick Bull
  • 9,518
  • 6
  • 36
  • 58
  • Two problems. Don't call `async` methods in constructors and don't use `async void` except for event handlers. – Dustin Kingen Apr 10 '14 at 14:55
  • 1.Never use `async void` methods exceptions for event handlers, 2.Show us how you constructed `SomeForm` what was the parameter you pass in it? Where does it comes from? – Sriram Sakthivel Apr 10 '14 at 14:55
  • 1
    your code sample is too incomplete. it's unknown what TaskA is or where it comes from – Dbl Apr 10 '14 at 15:00
  • Seems like your Task dosen't return.. can we see what it's doing? – Yuval Itzchakov Apr 10 '14 at 15:25
  • Updated the question with the Task's method. – Nick Bull Apr 10 '14 at 21:48
  • Is your task in a `Created` or a `Running` state before PerformTask is called? Your first example never appears to start the task, but your second very clearly does. The fact that you're able to call start in your second example *without getting an exception* suggests that your task wasn't started to begin with. – joshtkling Apr 10 '14 at 22:29

1 Answers1

2

The task does not continue past ReturnValue = await TaskA; because it is not returning. Verify the Task is running and not getting stuck.

To property utility async-await for object construction use an async factory method.

See: How to initialize an object using async-await pattern

public class Form1<T> : Form
{
    public Form1(string waitingText, Task<T> task)
    {
        Task = Execute(task);
        Controls.Add(new Label { Text = waitingText });
    }

    public T ReturnValue { get { return Task.Result; } }
    public Task<T> Task { get; private set; }

    private async Task<T> Execute(Task<T> task)
    {
        var result = await task;
        Close();
        return result;
    }
}

Usage:

var form = new Form1<int>("Hello", Task.Delay(1000).ContinueWith(_ => 1));
form.Show();

var returnValue = await form.Task;
Console.WriteLine(returnValue);
Community
  • 1
  • 1
Dustin Kingen
  • 20,677
  • 7
  • 52
  • 92