Ich entwickle eine Single-Form-App, die auf Knopfdruck eine einfache Inventory-Datenbank-API-Abfrage erstellt und jede zurückgegebene ItemID # auf ein entsprechendes Image überprüft kann oder darf nicht bei einer URL bestehen, die aus der ID # gebildet wird. Ich mache das gerade, indem ich HttpWebRequest.Method = "HEAD" -Anfragen für jede URL sende und true zurückgebe, bis der catch-Block ausgelöst wird.C# Async Mehrere Webanforderungen an DataTable - Arbeit scheint aus unbekannten Gründen zu stoppen
Die Datenbankabfrage kann 50 - 150 Teilenummern zurückgeben, und das Senden von HEAD-Anforderungen an jede einzelne auf diese Weise dauert etwa 5 Minuten und dies ist nicht produktiv.
Ich versuche, diesen Prozess mit async Multi-Task und warten. Wenn ich auf die Schaltfläche klicke, funktioniert es einwandfrei und lädt Zeilen nacheinander in mein DataGridView mit einer Rate von etwa 2/Sekunde (was nicht schlimm ist, aber ich würde das gerne noch beschleunigen, wenn möglich).
ABER: Nach dem Finden von 2 erfolgreichen URL-Antworten hört es auf, Zeilen zu laden und scheint aufzugeben, aus Gründen, die mir unbekannt sind ??? Und der Block syncContext, der die Benutzeroberfläche wieder aktiviert, wird nie ausgeführt, da die Arbeit nie abgeschlossen wird. Kann jemand sehen, was das verursachen könnte?
Ich habe gearbeitet, basiert weg lose dieses doc:
"Gewusst wie: Erstellen Sie mehrere Web Requests parallel von Asynchron-Verwendung und warten (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();
}
Sie sind in TAP verpasst und Asynchron/await . Es ist ein falscher Ansatz, ein aufgabenbasiertes asynchrones Muster zu implementieren und zu verwenden. –
Hamlet, ist es das, was es zum Stillstand bringt, oder wäre es einfach weniger Aufwand, wenn es anders geht? Vielleicht könnten Sie mir Unterlagen zur Verfügung stellen oder mir sagen, welche Zeilen durcheinander geraten sind? – mholberger
google mit Schlüsselwörtern TAP, async/await, aufgabenbasiertes asynchrones Muster. –