我正在開發一個單一的表單應用程序,按下按鈕,使一個簡單的庫存數據庫API查詢,並檢查每個返回的ItemID#對應的圖像可能存在或不存在於由ID#形成的URL。我目前正在通過爲每個URL發送HttpWebRequest.Method =「HEAD」請求來做到這一點,除非catch塊被觸發,否則返回true。C#異步多個Web請求到DataTable - 工作似乎停止不明原因
數據庫查詢可能會返回50-150個零件號碼,並且以這種方式單獨向每個零件發送HEAD請求需要大約5分鐘,這不是生產性的。
我想多任務這個過程使用異步和等待。當我點擊按鈕時,它可以正常工作,以約2 /秒的速率將行異步加載到我的DataGridView中(這並不壞,但如果可能的話,我仍然希望加快速度)。但是,在找到2個成功的URL響應後,它停止加載行,似乎只是放棄,因爲我不知道的原因?並且重新啓用UI的syncContext塊永遠不會執行,因爲工作從未完成。任何人都可以看到什麼可能導致這種情況發生?
我一直在努力鬆散的基礎關閉該文檔:
「如何:使用異步使多個並行的Web請求,並等待(C#)」 https://msdn.microsoft.com/en-us/library/mt674880.aspx
namespace ImageTableTest
{
public partial class ImageTableTestForm : Form
{
//P21 Authentication Variables
private static Token P21token = null;
private static RestClientSecurity rcs;
//Create Tables and bindingSource
DataTable itemDataIMG = new DataTable();
DataTable itemDataNOIMG = new DataTable();
DataTable itemDataComplete = new DataTable();
BindingSource bindingSource = new BindingSource();
private readonly SynchronizationContext synchronizationContext;
public ImageTableTestForm()
{
InitializeComponent();
//Create syncContexct on UI thread for updating UI
synchronizationContext = SynchronizationContext.Current;
//authenticate database API function
authenticateP21();
//Designing DataTables
itemDataIMG.Columns.Add("MPN#", typeof(string));
itemDataIMG.Columns.Add("IMG", typeof(bool));
itemDataIMG.Columns[1].ReadOnly = true;
itemDataNOIMG.Columns.Add("MPN#", typeof(string));
itemDataNOIMG.Columns.Add("IMG", typeof(bool));
itemDataNOIMG.Columns[1].ReadOnly = true;
itemDataComplete.Columns.Add("MPN#", typeof(string));
itemDataComplete.Columns.Add("IMG", typeof(bool));
itemDataComplete.Columns[1].ReadOnly = true;
//bind to DataGridView itemView
bindingSource.DataSource = itemDataComplete;
itemView.DataSource = bindingSource;
itemView.AutoGenerateColumns = false;
}
private async void testBtn_Click(object sender, EventArgs e)
{
//When button is clicked, disable UI and
//start background work:
testBtn.Enabled = false;
loadSpinner.Visible = true;
await Task.Run(() =>
{
getItemView();
});
}
private async void getItemView()
{
try
{
//This executes the query and returns an array of Part objects:
PartResourceClient prc = new PartResourceClient(ConfigurationManager.AppSettings["P21.BaseURI"], rcs);
prc.QueryFilter("add_to_ebay eq 'Y'");
Part[] pResults = prc.Resource.GetParts();
int numParts = pResults.Length;
Task<bool>[] taskArray = new Task<bool>[numParts];
bool[] IMGboolArray = new bool[numParts];
//For each part, create CheckImageURL task and add to task Array
//Then Await execution
for (int i = 0; i < numParts; i++)
{
taskArray[i] = CheckImageURL(pResults[i].ItemId);
IMGboolArray[i] = await taskArray[i];
}
}
catch (Exception e)
{
MessageBox.Show(e.ToString());
}
//When all Tasks finish, remove loadSpinner, re-enable UI
//(This never executes for unknown reasons.)
synchronizationContext.Post(new SendOrPostCallback(o =>
{
loadSpinner.Visible = false;
testBtn.Enabled = true;
}), null);
MessageBox.Show("<DONE>");
}
async Task<bool> CheckImageURL(string MPN)
{
//Here I am forming and executing the web HEAD request,
//If there is there is a 'NOT FOUND' response it goes to 'catch' block:
string URL = "https://s3-us-west-2.amazonaws.com/www.crosscreektractor.com/ebay-images/" + MPN + "_e.png";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(URL);
request.Method = "HEAD";
try
{
await request.GetResponseAsync();
synchronizationContext.Post(new SendOrPostCallback(o =>
{
addDataRows(MPN, true);
}), null);
return true;
}
catch
{
synchronizationContext.Post(new SendOrPostCallback(o =>
{
addDataRows(MPN, false);
}), null);
return false;
}
}
private void addDataRows(string MPN, bool IMG)
{
//Add data to respective table:
if (IMG)
{
itemDataIMG.Rows.Add(MPN, IMG);
}
else
{
itemDataNOIMG.Rows.Add(MPN, IMG);
}
//Here I am sorting the IMG and NOIMG tables,
//then merging them into the Complete table which
//The DataGridView is bound to, so that IMG entries are on top:
itemDataIMG.DefaultView.Sort = ("MPN# DESC");
itemDataNOIMG.DefaultView.Sort = ("MPN# DESC");
itemDataComplete.Clear();
itemDataComplete.Merge(itemDataIMG);
itemDataComplete.Merge(itemDataNOIMG);
itemView.Refresh();
}
在TAP和異步/等待中錯過了。實現和使用基於任務的異步模式是錯誤的。 –
哈姆雷特,是什麼導致它失速,或者如果做得不同,它會降低開銷嗎?也許你可以提供文檔或告訴我哪些行看起來混亂? – mholberger
google通過關鍵字TAP,async/await,基於任務的異步模式。 –