버튼 누르기에서 간단한 인벤토리 데이터베이스 API 쿼리를 만들고, 반환 된 각 ItemID를 확인하는 단일 양식 앱을 개발 중입니다. ID #에서 형성된 URL에 존재할 수도 있고 존재하지 않을 수도있다. 나는 현재 각 URL에 대해 HttpWebRequest.Method = "HEAD"요청을 보내서이를 수행하고 있으며 catch 블록이 트리거되지 않는 한 true를 반환합니다.DataTable에 대한 비동기 다중 웹 요청 - 알 수없는 이유로 작업이 멈춘 것처럼 보입니다.
데이터베이스 쿼리는 50-150 개의 부품 번호를 반환 할 수 있으며 이러한 방식으로 개별적으로 HEAD 요청을 보내는 데 약 5 분이 소요되며 이는 생산적이지 않습니다.
이 프로세스를 async와 await을 사용하여 다중 작업하려고합니다. 버튼을 클릭하면 비동기 적으로 DataGridView에 행을 한 개씩 하나씩로드 할 수 있습니다. 속도는 약 2/초 (나쁘지는 않지만 가능하면이 속도를 높이는 것이 좋습니다)입니다.
두 개의 성공적인 URL 응답을 찾으면 행로드가 중지되고 나에게 알 수없는 이유로 포기하는 것처럼 보입니다. ??? 그리고 작업이 완료되지 않기 때문에 UI를 다시 활성화하는 syncContext 블록은 실행되지 않습니다. 아무도 이것이 일어날 수있는 원인을 볼 수 있습니까?
:
내가 느슨하게 일하고있다이 문서 기반으로 "방법 : 비동기를 사용하여 병렬로 여러 웹 요청을하고 기다리고 있습니다 (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 놓친 및 비동기/await를하고 있습니다 . 작업 기반 비동기 패턴을 구현하고 사용하는 것은 잘못된 접근 방식입니다. –
햄릿 (Hamlet), 햄릿이 멈추는 원인이 무엇입니까? 그렇지 않으면 다르게 수행하면 오버 헤드가 낮아 집니까? 어쩌면 당신은 문서를 제공하거나 어떤 라인이 엉망으로 보이는지 말할 수 있습니까? – mholberger
google by 키워드 TAP, async/await, 작업 기반 비동기 패턴. –