[英]My desktop application hangs on web API service call with async and await
在數據庫中保存數據時,我遇到了很多延遲。 我有一個exe(Deskptop應用程序)從串口讀取數據並通過Web API服務將該條目推送到數據庫,但我的應用程序在此行上掛起:
httpClient.PostAsync("api/MyController/Save", httpConent).Result;
這個exe負責調用我的Web API服務方法並將數據保存到我的數據庫。
這是我的代碼:
void _serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
int dataLength = _serialPort.BytesToRead;
byte[] data = new byte[dataLength];
int nbrDataRead = _serialPort.Read(data, 0, dataLength);
if (nbrDataRead == 0)
return;
// Send data to whom ever interested
if (NewSerialDataRecieved != null)
{
NewSerialDataRecieved(this, new SerialDataEventArgs(data));
}
}
void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
{
if (this.InvokeRequired)
{
// Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
//// Fired-off asynchronously; let the current thread continue.
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataRecieved), new object[] { sender, e });
return;
}
//data is converted to text
string str = Encoding.ASCII.GetString(e.Data);
if (!string.IsNullOrEmpty(str))
{
CallWebservice(str)
}
}
public void CallWebservice(string xmlRequest)
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri("WebService Url");
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
StringContent httpConent = new StringContent(xmlRequest, Encoding.UTF8);
HttpResponseMessage responseMessage = null;
try
{
responseMessage = httpClient.PostAsync("api/MyController/Save", httpConent).Result;
}
catch (Exception ex)
{
if (responseMessage == null)
{
responseMessage = new HttpResponseMessage();
}
responseMessage.StatusCode = HttpStatusCode.InternalServerError;
responseMessage.ReasonPhrase = string.Format("RestHttpClient.SendRequest failed: {0}", ex);
}
}
}
我的web api方法:
public async Task<HttpResponseMessage> Save(HttpRequestMessage request)
{
var requestdata = request.Content.ReadAsStringAsync().Result;//extract Users Id's from this
var users=context.User.Where(t => (t.Stats == userId1) || (t.Stats == userId2)).ToList();
var objUsersMapping= new UsersMapping();
objUsersMapping.Work1 = users[0].Work1;
objUsersMapping.Work2 = users[1].Work1;
await this.SaveUsersMapping(objUsersMapping);
}
public async Task<UsersMapping> SaveUsersMapping(UsersMapping objUsersMapping)
{
using (var context = new MyEntities())
{
try
{
context.UsersMapping.Add(objUsersMapping);
await context.SaveChangesAsync();
return objUsersMapping;
}
catch (Exception foExe)
{
return null;
}
}
}
我沒有在Windows應用程序上工作太多,所以我不明白為什么我的應用程序掛起。
注意 :數據將不斷進入我的串口,因此通過Web服務保存數據不應該干擾_serialPort_DataReceived
事件。
這是我在OP問題下的評論摘要
您正在同步調用異步方法。 這將導致當前線程阻塞。 擺脫.Result
並相應地改變其余的代碼(比如包括async
和await
那里)。
例如改變這一行
responseMessage = httpClient.PostAsync("api/MyController/Save", httpConent).Result;
...至:
responseMessage = await httpClient.PostAsync("api/MyController/Save", httpConent);
您的方法簽名需要更改如下:
public async Task CallWebservice(string xmlRequest)
{
}
調用它的任何方法也需要是async
並使用await
例如_spManager_NewSerialDataRecieved()
方法。
請注意,它已從void
更改為async void
。 CallWebservice()
請注意,在CallWebservice()
之前await
。
async void _spManager_NewSerialDataRecieved(object sender, SerialDataEventArgs e)
{
if (this.InvokeRequired)
{
// Using this.Invoke causes deadlock when closing serial port, and BeginInvoke is good practice anyway.
//// Fired-off asynchronously; let the current thread continue.
this.BeginInvoke(new EventHandler<SerialDataEventArgs>(_spManager_NewSerialDataRecieved), new object[] { sender, e });
return;
}
//data is converted to text
string str = Encoding.ASCII.GetString(e.Data);
if (!string.IsNullOrEmpty(str))
{
await CallWebservice(str)
}
}
因為上面的方法是一個事件處理程序,所以該方法可以是async void
。 通常,您希望避免非事件處理程序代碼中的async void
。 欲了解更多信息,請參閱Stephen Cleary先生的精彩文章 。
先生,這是唯一的問題嗎?
您應該在服務器上修復async Save()
方法,因為它也有.Result()
。 這將阻止服務器上的當前線程。 用await
前綴。 通常你想避免使用.Result
作為等待任務完成的手段 。 在等待它之后,可以安全地使用它作為獲取結果的方法,但是有更優雅的方法可以等待並在單行代碼中獲得結果。 例如x = await FooAsync();
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.