我想学习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关键字进行操作。有更好的方法吗?
答案 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