c # многопоточность лучшие практики - PullRequest
0 голосов
/ 12 мая 2019

Я хочу научиться правильной многопоточности в C #. Я хочу создать программу для доступа к нескольким API для получения информации. Чтобы уменьшить трафик, они будут сохранены локально и обновлены только после времени X. Затем мне нужно получить доступ к некоторым веб-страницам с http по умолчанию, чтобы прочитать HTML, чтобы получить остальную часть моей необходимой информации. Просто чтобы выучить его, я хочу получить как можно больше параллели и не блокировать его. Я нашел решение для этого здесь: https://stackoverflow.com/a/18033198/8953694 с этим я создал мой. На данный момент это просто загрузить / сохранить ключи API из пользовательского интерфейса, но я бы использовал этот стиль для всего остального, что я буду делать. Это хороший способ сделать это?

Мой код:

`C #

private async void Load()
{
    try
    {
        JsonAPI jsonAPI = await Task.Run(() => UIHandler.LoadSettingsAsync());
        bapi_client_ID.Text = jsonAPI.Dienst[0].ApiKey[0].Key;
        bapi_Client_Secret.Text = jsonAPI.Dienst[0].ApiKey[1].Key;
    }
    catch (Exception error)
    {
        statusBar.Text = "Error: " + error.Message;
    }
}
private async void Save_settings_Click(object sender, RoutedEventArgs e)
{
    save_settings.IsEnabled = false;
    statusBar.Text = "Save settings...";
    try
    {
        JsonAPI jsonAPI = ConvertAPIJson();
        await Task.Run(() => UIHandler.SaveSettingsAsync(jsonAPI));
    }
    catch (Exception error)
    {
        statusBar.Text = "Error: " + error.Message;
    }
    statusBar.Text = "Settings saved!";
    save_settings.IsEnabled = true;
}
public static async Task SaveSettingsAsync(JsonAPI jsonAPI)
{
    byte[] encodedText = Encoding.Unicode.GetBytes(JsonConvert.SerializeObject(jsonAPI));

    using (FileStream fs = new FileStream(@"API.json", FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
    {
        fs.SetLength(0);
        await fs.WriteAsync(encodedText, 0, encodedText.Length);
    }
}        
public static async Task<JsonAPI> LoadSettingsAsync()
{
    byte[] encodedText;

    using (FileStream fs = new FileStream(@"API.json", FileMode.OpenOrCreate, FileAccess.Read, FileShare.None))
    {
        encodedText = new byte[(int)fs.Length];
        await fs.ReadAsync(encodedText, 0, (int)fs.Length);
    }

    return JsonConvert.DeserializeObject<JsonAPI>(Encoding.Unicode.GetString(encodedText));
}

``

Чтобы изменить элементы пользовательского интерфейса, я бы сделал это с ключевым словом прогресса, как в примере. Есть ли лучшие способы сделать это?

1 Ответ

0 голосов
/ 12 мая 2019

Удалить Task.Run оболочки, методы «Загрузка» и «Сохранить» являются асинхронными и могут быть вызваны без него.

private async void Load()
{
    var settings = await UIHandler.LoadSettingsAsync();

    bapi_client_ID.Text = settings.Dienst[0].ApiKey[0].Key;
    bapi_Client_Secret.Text = settings.Dienst[0].ApiKey[1].Key;
}

private async void Save_settings_Click(object sender, RoutedEventArgs e)
{
    statusBar.Text = "Save settings...";

    var settings = ConvertAPIJson();
    await UIHandler.SaveSettingsAsync(settings);

    statusBar.Text = "Settings saved!";
}

При доступе к внешним ресурсам (веб-сервисам, базе данных, файловой системе) асинхроннымПодход обеспечивает возможность доступа к внешним ресурсам в разблокированном виде и в пределах одного потока.
Оборачивая этот вид методов другим потоком, вы просто тратите поток, который ничего не выполняет, но только ожидает ответа.

Примеры этикет Task.Run: не используйте Task.Run для неправильной вещи

...