Вызов InsertAsync из статической функции вызывает исключение ThreadAbortException

1

Я ожидаю, что, возможно, это простое исправление, но я просто не вижу его.

Я пытаюсь вставить данные в базу данных Azure Mobile Services из программы консоли С#. Однако, когда программа запускается из VS (через F5), данные не вставляются и не генерируются исключение (что я вижу) во время обычного хода запуска программы. Когда я устанавливаю await dataModel.InsertAsync(data) останова на await dataModel.InsertAsync(data) и запускаю ее в окне Immediate, она генерирует исключение 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;
    }

}
}
  • 0
    Что происходит, когда вы ставите точку останова в строке var x = InsertItem (test) и проверяете x? Я подозреваю, вы обнаружите, что это задача, и нет соответствующего вызова run ... но ... я просто догадываюсь.
  • 0
    Markus - на самом деле, когда я устанавливаю InsertAsync останова и через F11, сеанс отладки останавливается сразу после вызова InsertAsync .
Показать ещё 4 комментария
Теги:
azure

2 ответа

1
Лучший ответ

Я создал небольшой тест, чтобы (несколько) смоделировать то, что вы делаете. Когда ожидаемая задача в InsertItem занимает совсем немного времени или нет, задача, возвращаемая строкой var x = InsertItem (test), возвращает задачу в состоянии RanToCompletion, и отладчик действует так, как ожидалось.

Однако, когда я делаю ожидаемую задачу, делаю что-то существенное, например Thread.Sleep(5000), тогда я получаю описанное поведение, а задача, возвращаемая с помощью строки var x = InsertItem (test), возвращает задачу в WaitingForActivation государство.

Когда я ставил Task.WaitAll(x) после строки var x = InsertItem (test), тогда я получаю поведение, которое, как я думаю, мы ожидаем, и x.Status - это RanToCompletion.

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 если вы не находитесь в функции делегата события

Ещё вопросы

Сообщество Overcoder
Наверх
Меню