API 的异步方法调整变量,然后变量处于其原始状态
本文关键字:变量 于其 原始 原始状 状态 异步方法 调整 API 然后 | 更新日期: 2023-09-27 18:36:14
好吧,所以我使用eID读卡器从ID卡中获取姓名等,然后使用以下方法要查看数据库中是否已有人具有完全相同的信息,请执行以下操作:
private async void GetCustomer()
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync("http://localhost:32576/api/customer?name=" + EIDCustomer.CustomerName + "&address=" + EIDCustomer.Address);
if(response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
ApplicationVM.customer = JsonConvert.DeserializeObject<Customer>(json);
}
else
{
Console.Write("api fail");
}
}
}
好的,ApplicationVM.customer
如下:"public static Customer customer = null;
" GetCustomer()
正在通过以下方法调用:
private Customer GetCustomerFromIDReader()
{
Customer c = new Customer();
try
{
//BEID_ReaderSet.initSDK();
BEID_ReaderSet readerSet = BEID_ReaderSet.instance();
BEID_ReaderContext reader = readerSet.getReader();
if(reader.isCardPresent())
{
BEID_EIDCard card = reader.getEIDCard();
BEID_EId doc = card.getID();
string firstName = doc.getFirstName();
string lastName = doc.getSurname();
int postCode = Int32.Parse(doc.getZipCode());
string straatEnNr = doc.getStreet().Trim();
string gemeente = doc.getMunicipality();
c.CustomerName = firstName + "" + lastName;
c.Address = straatEnNr + ";" + postCode + ";" + gemeente;
c.Picture = card.getPicture().getData().GetBytes();
}
else
{
c = null;
}
BEID_ReaderSet.releaseSDK();
}
catch (BEID_Exception ex)
{
Console.Write("Er is iets misgelopen bij het inlezen van de eID");
return null;
}
EIDCustomer = c;
GetCustomer();
return c;
}
EIDCustomer 是"客户"类型的属性。好吧,那么程序应该检查c是否为空,如果不是,那么它检查ApplicationVM.customer是否为空。如果是这样,您将被重定向到要求您创建新帐户的窗口。如果ApplicationVM.customer不为空,则可以转到下一个窗口。这是代码:
public ICommand LoginCommand
{
get
{
return new RelayCommand(Login);
}
}
public void Login()
{
ApplicationVM appvm = App.Current.MainWindow.DataContext as ApplicationVM;
Customer c = new Customer();
c = GetCustomerFromIDReader();
if(c == null)
{
Console.Write("Er is iets fout gelopen bij het inlezen van de e-IDkaart");
}
else if (ApplicationVM.customer == null)
{
appvm.ChangePage(typeof(KlantNieuwVM));
}
else
{
appvm.ChangePage(typeof(KlantenInterfaceVM));
}
}
(我与UserControls合作更改页面,我总是在MainWindow上,但我认为这对这个问题没有任何意义。
这是在 API 中调用的方法:
public Customer Get(string name, string address)
{
return CustomerDA.CheckCustomerLogin(name, address);
}
CustomerDA.CheckCustomerLogin
只是一个SQL语句,用于检查数据库中是否有具有完全相同名称和地址的人。
您遇到的问题是您的GetCustomer()
方法是异步的,并且您没有等待它。因此,当您点击HttpResponseMessage
行时:
HttpResponseMessage response = await client.GetAsync("");
控制权将返回到您的命令,并且在请求返回之前继续执行。
您可以通过使命令异步来解决此问题。
当您使用 async/await 模式时,整个调用链需要是可等待的,否则您将遇到此问题。
GetCustomerFromIDReader
private async Task<Customer> GetCustomerFromIDReader()
{
Customer c = new Customer();
// .... redacted for clarity
await GetCustomer();
return c;
}
命令用法
public ICommand LoginCommand
{
get
{
return new RelayCommand(async () => await Login());
}
}
public async Task Login()
{
ApplicationVM appvm = App.Current.MainWindow.DataContext as ApplicationVM;
Customer c = new Customer();
c = await GetCustomerFromIDReader();
if(c == null)
{
Console.Write("Er is iets fout gelopen bij het inlezen van de e-IDkaart");
}
else if (ApplicationVM.customer == null)
{
appvm.ChangePage(typeof(KlantNieuwVM));
}
else
{
appvm.ChangePage(typeof(KlantenInterfaceVM));
}
}
最后,更改您的GetCustomer
以返回任务并且不会无效。
获取客户
private async Task GetCustomer()
{
using (HttpClient client = new HttpClient())
{
HttpResponseMessage response = await client.GetAsync("");
if(response.IsSuccessStatusCode)
{
string json = await response.Content.ReadAsStringAsync();
ApplicationVM.customer = JsonConvert.DeserializeObject<Customer>(json);
}
else
{
Console.Write("api fail");
}
}
}
正如我在有关异步最佳实践的 MSDN 文章中解释的那样,请避免async void
。
因此,您的async void
方法应async Task
:
private async Task GetCustomerAsync()
{
...
}
当它被调用时,它应该被await
ed,这反过来又使调用方法async
:
private async Task<Customer> GetCustomerFromIDReaderAsync()
{
...
EIDCustomer = c;
await GetCustomerAsync();
return c;
}
调用该方法的方法也是如此:
public async Task LoginAsync()
{
ApplicationVM appvm = App.Current.MainWindow.DataContext as ApplicationVM;
Customer c = new Customer();
c = await GetCustomerFromIDReaderAsync();
if(c == null)
{
Console.Write("Er is iets fout gelopen bij het inlezen van de e-IDkaart");
}
else if (ApplicationVM.customer == null)
{
appvm.ChangePage(typeof(KlantNieuwVM));
}
else
{
appvm.ChangePage(typeof(KlantenInterfaceVM));
}
}
最后,您最终得到ICommand
实现,您可以在其中使用async void
(因为它在逻辑上是一个事件处理程序):
public ICommand LoginCommand
{
get
{
return new RelayCommand(async () => { await LoginAsync(); });
}
}
但是,在处理异步命令时,您需要考虑几点。这个简单的示例不会在执行时禁用ICommand
,也不会干净地处理异常。我有另一篇专门介绍异步 MVVM 命令的 MSDN 文章。