c#多线程最佳做法

时间:2019-05-12 16:45:50

标签: c# multithreading async-await task

我想学习C#中正确的多线程。我想创建一个访问多个API以获得信息的程序。为了减少流量,这些内容将被保存在本地并仅在时间X之后进行更新。然后,我需要访问一些带有默认http的网页,以读取HTML来获取其余的所需信息。只是为了学习它,我想让它尽可能并行和无阻塞。我在这里找到了解决方案:https://stackoverflow.com/a/18033198/8953694是我创建的。现在,它只是从UI加载/保存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));
}

``

要更改UI元素,就像示例中一样,我将使用progress关键字进行操作。有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

删除#include<vector> #include"z3++.h" using namespace std; using namespace z3; int main(void) { context c; expr_vector variables(c); variables.push_back(c.int_const("x")); variables.push_back(c.int_const("y")); variables.push_back(c.int_const("z")); expr x = variables[0]; expr y = variables[1]; expr z = variables[2]; solver s(c); s.add(5 <= x+y+z); s.add(x+y+z <= 16); s.add(-4 <= x-y); s.add(x-y <= 6); s.add(-1 <= x-z); s.add(x-z <= 7); s.add(x >= 0); s.add(y >= 0); s.add(z >= 0); while (s.check() == sat) { model m = s.get_model(); cout << m << endl; cout << "#######" << endl; expr tmp = c.bool_val(false); for(int i = 0; i < variables.size(); ++i) { tmp = tmp || (variables[i] != m.eval(variables[i])); } s.add(tmp); } return 0; } 包装程序,“加载”和“保存”方法是异步的,没有它们也可以调用。

Task.Run

当访问外部资源(Web服务,数据库,文件系统)时,异步方法提供了一种可能性,可以在一个线程内以非阻塞方式访问外部资源。
通过将这种方法包装到另一个线程中,您只是在浪费一个线程,该线程什么也不执行,而只是等待响应。

Task.Run Etiquette Examples: Don't Use Task.Run for the Wrong Thing