从静态函数调用InsertAsync会抛出ThreadAbortException

时间:2014-06-10 23:09:11

标签: c# azure

我希望这可能是一个简单的解决办法,但我无法看到它。

我尝试从C#控制台程序将数据插入Azure移动服务数据库。但是,当程序从VS内部运行时(通过F5),数据没有被插入,也没有在运行程序的常规过程中抛出异常(我可以看到)。当我将断点设置为await dataModel.InsertAsync(data)行并在立即窗口中运行它时会抛出一个ThreadAbortException。任何帮助表示赞赏。

Namespace TestApp {
class Program
{
    public static MobileServiceClient MobileService = new MobileServiceClient(
    "https://x.azure-mobile.net/",
    "API key");

    public static IMobileServiceTable<performance> dataModel = Program.MobileService.GetTable<performance>();

    static void Main(string[] args)
    {
        try
        {
            var test = new performance("http://www.example.com");
            var x = InsertItem(test);
        }
        catch (Exception ex)
        {
            System.Diagnostics.Debug.WriteLine(ex.StackTrace);
        }
    }
static public async Task InsertItem(performance data)
{
        await dataModel.InsertAsync(data).ConfigureAwait(false);
}
}

class performance
{
    [JsonProperty(PropertyName = "id")]
    string Id { get; set; }
    [JsonProperty(PropertyName = "uri")]
    string Uri { get; set; }

    public performance(string uri)
    {
        Uri = uri;
    }

}
}

2 个答案:

答案 0 :(得分:3)

您的问题来自var x = InsertItem(test);是非阻止呼叫的事实。当您到达await dataModel.InsertAsync(data).ConfigureAwait(false);时,函数InsertItem会立即返回Task

通常情况下,正确的方法是await InsertItem(test);但是因为您的代码是从Main调用的,所以您无法创建函数async。所以对于这个控制台应用程序(如果在WinForms或WPF应用程序中运行,它将不是正确的选择)您需要在x.Wait()块结束之前放置try-catch

static void Main(string[] args)
{
    try
    {
        var test = new performance("http://www.example.com");
        var x = InsertItem(test);

        //This makes the program wait for the returned Task to complete before continuing.
        x.Wait();
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
    }
}

但是,如果您在WPF或WinForms应用程序中执行此操作,您只需将调用函数(假设函数是一个事件)async。

private async void Button1_OnClick(object sender, EventArgs e)
{
    try
    {
        var test = new performance("http://www.example.com");

        //The code now waits here for the function to finish.
        await InsertItem(test);
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine(ex.StackTrace);
    }
}

除非您处于事件委托功能

,否则不要进行async void次函数调用

答案 1 :(得分:1)

我创建了一个小测试(有些)模拟你正在做的事情。当InsertItem中等待的任务花费很少或根本没有时间时,var x = InsertItem(test)行返回的任务返回RanToCompletion状态的任务,调试器按预期运行。

然而,当我让等待的任务做一些实质性的事情,比如Thread.Sleep(5000),然后我得到你正在描述的行为,并且var x = InsertItem(test)行返回的任务返回一个任务处于WaitingForActivation状态。

当我在var x = InsertItem(test)行之后放置Task.WaitAll(x)时,我得到了我认为我们都期望的行为,而x.Status是RanToCompletion。