异步和等待任务已丢失

时间:2018-06-28 02:16:57

标签: c# async-await

我收到“因为未等待此电话...”

SendPostAsync(CustomerName, email, Phone, maxImages, MainEventName, MainEventCode, CLemail, package_type, PlayerInfo, template_ID, favoritesArray);

在此单击按钮:

private void btnCopyAllInvoices_Click(object sender, EventArgs e)
{
    //sets up a list to store the incoming invoice numbers from the DB
    List<string> InvoiceNums = new List<string>();
    mySqlInterface.Connect();

    InvoiceNums = mySqlInterface.GetNewInvoices();

    //prep the visuals
    lblStatus.Text = "";
    InvoicePanel.Visible = true;
    progressBarInvoice.Value = 0;
    progressBarInvoice.Maximum = InvoiceNums.Count;

    //for each invoice collected let's copy it
    InvoiceNums.ForEach(delegate(string inv)
    {
        if (OrderDAL.CheckOrderExist(inv))
        {
            // the order already exist
            Order myorder = new Order();
            myorder = OrderDAL.GetOrder(inv);

            CopyImages(myorder, true);

            OrderDAL.UpdateFulfillment(string.Format("Images Copied"), inv);

        }

    });

    //let the user know how we did
    MessageBoxButtons buttons = MessageBoxButtons.OK;
    string strError = string.Format("{0} Invoices copied.", InvoiceNums.Count);
    MessageBox.Show(this, strError, "Copy New Invoices", buttons, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);

    InvoicePanel.Visible = false;
}

在这里,CopyImages被称为上述foreach循环的一部分。

public void CopyImages(Order order, bool CopyAllInv)
{
    string baseTarget = WorkSpace.Text;
    string CLhotfolderTarget = string.Empty;

    //check to see if the order has been photo released.  If it has add "pr" to the end of the invoice number
    string prInvoice = "";
    if (order.Header.SignatureLine != "null" && order.Header.SignatureChecks != "null")
    {
        prInvoice = "pr";
    }

    string PackageName = null;
    string CustomerName = null;
    string Phone = null;
    string email = null;
    string PlayerInfo = null;
    string PlayerName = null;
    string PlayerNumber = null;
    string MainEventName = null;
    string MainEventCode = null;
    string CLemail = null;

    //go to the DB and get the info
    mySqlInterface.Connect();
    bool videoPackage = mySqlInterface.VideoInfo(order.Header.InvoiceNumber, out PackageName, out CustomerName, out Phone, out email, out PlayerName, out PlayerNumber, out MainEventName, out MainEventCode);
    mySqlInterface.Close();

    if (videoPackage)
    {
        if (PackageName.Contains("Video") || PackageName.Contains("Ultimate Ripken"))
        {
            CLemail = MainEventCode + "_" + email.Replace("@", "_").Replace(".", "_").Replace("+", "_"); 
            PlayerInfo = PlayerName + " " + PlayerNumber;

            int template_ID = 0;
            if (txtCLtemplateID.Text != "")
            {
                template_ID = Convert.ToInt32(txtCLtemplateID.Text);
            }

            //we will always need a hotfolder.  So let's set and create it now
            CLhotfolderTarget = txtCLhotfolder.Text + "\\toUpload\\" + CLemail;
            if (!System.IO.Directory.Exists(CLhotfolderTarget))
            {
                // create the directory
                System.IO.Directory.CreateDirectory(CLhotfolderTarget);
            }

            int maxImages = 7;
            int package_type = 2;
            string[] favoritesArray = new string[maxImages];

            //populate the array of images for the video
            int count = 0;
            foreach (Order.InvoiceImages image in order.ImageList)
            {
                favoritesArray[count] = image.ImageName;
                count++;
            }

            //let's call the API and send info to CL
            SendPostAsync(CustomerName, email, Phone, maxImages, MainEventName, MainEventCode, CLemail, package_type, PlayerInfo, template_ID, favoritesArray);
        }
    }
}


public async Task SendPostAsync(string name, string email, string phone, int photo_count, string event_name, string event_id, string dir_name, int package_type, string video_text, int template_id, string[] favoritesArray)
{
    string postURL = null;
    string token = null;
    int delivery_method = 2;

    //production
    postURL = "https://search.apicall.com/photographer/customer";
    token = "token xxxxxxxxxxxxxxxxxxxxx";              

    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(postURL);
    client.DefaultRequestHeaders.Add("Authorization", token);
    string POSTcall = JsonConvert.SerializeObject(new { name, email, phone, photo_count, event_id, event_name, dir_name, package_type, video_text, delivery_method, template_id, favorites = favoritesArray });


    //Send string to log file for debug
    WriteLog(POSTcall);


    StringContent stringContent = new StringContent(POSTcall, UnicodeEncoding.UTF8, "application/json");


    HttpResponseMessage response = await client.PostAsync(new Uri(postURL), stringContent);
    string POSTresponse = await response.Content.ReadAsStringAsync();
    WriteLog(POSTresponse);

    //simplified output for debug
    if (POSTresponse.Contains("error") && POSTresponse.Contains("false"))
    {
        lblStatus.Text = "Error Sending to CL";
    }
    else
    {
        lblStatus.Text = "Successfully added to CL";
    }

}

我正在等待HttpResponseMessage response = await client.PostAsync

如果我一次运行该程序,它将起作用。但是,当我循环执行此操作时,又有很多背靠背的感觉,我认为PostAsyncs正在逐步发展。我在WriteLog中缺少整个物品。

似乎我需要在上游进行异步/唤醒,对吗?这样,我可以运行整个方法。

1 个答案:

答案 0 :(得分:0)

引用Async/Await - Best Practices in Asynchronous Programming,事件处理程序允许async void,因此重构代码以使其始终保持异步状态。

重构CopyImages以等待数据发布

public async Task CopyImages(Order order, bool CopyAllInv) {
    //...omitted for brevity

    if (videoPackage) {
        if (PackageName.Contains("Video") || PackageName.Contains("Ultimate Ripken")) {
            //...omitted for brevity

            await SendPostAsync(CustomerName, email, Phone, maxImages, MainEventName, MainEventCode, CLemail, package_type, PlayerInfo, template_ID, favoritesArray);
        }
    }
}

并更新事件处理程序

private async void btnCopyAllInvoices_Click(object sender, EventArgs e) {
    //sets up a list to store the incoming invoice numbers from the DB
    List<string> InvoiceNums = new List<string>();
    mySqlInterface.Connect();

    InvoiceNums = mySqlInterface.GetNewInvoices();

    //prep the visuals
    lblStatus.Text = "";
    InvoicePanel.Visible = true;
    progressBarInvoice.Value = 0;
    progressBarInvoice.Maximum = InvoiceNums.Count;

    //for each invoice collected let's copy it
    foreach(string inv in InvoiceNums) {
        if (OrderDAL.CheckOrderExist(inv)) {
            // the order already exist
            Order myorder = OrderDAL.GetOrder(inv);

            await CopyImages(myorder, true);

            OrderDAL.UpdateFulfillment(string.Format("Images Copied"), inv);    
        }
    }

    //let the user know how we did
    MessageBoxButtons buttons = MessageBoxButtons.OK;
    string strError = string.Format("{0} Invoices copied.", InvoiceNums.Count);
    MessageBox.Show(this, strError, "Copy New Invoices", buttons, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);

    InvoicePanel.Visible = false;
}

我也建议不要为每个帖子请求创建一个HttpClient。提取出来并使用一个客户端。

static Lazy<HttpClient> httpClient = new Lazy<HttpClient>(() => {
    var postURL = "https://search.apicall.com/photographer/customer";
    var token = "token xxxxxxxxxxxxxxxxxxxxx";
    HttpClient client = new HttpClient();
    client.BaseAddress = new Uri(postURL);
    client.DefaultRequestHeaders.Add("Authorization", token);
    return client
});

public async Task SendPostAsync(string name, string email, string phone, int photo_count, string event_name, string event_id, string dir_name, int package_type, string video_text, int template_id, string[] favoritesArray)
{
    var postURL = "https://search.apicall.com/photographer/customer";
    int delivery_method = 2;

    string POSTcall = JsonConvert.SerializeObject(new { name, email, phone, photo_count, event_id, event_name, dir_name, package_type, video_text, delivery_method, template_id, favorites = favoritesArray });    

    //Send string to log file for debug
    WriteLog(POSTcall);    

    StringContent stringContent = new StringContent(POSTcall, UnicodeEncoding.UTF8, "application/json");    

    HttpResponseMessage response = await httpClient.Value.PostAsync(new Uri(postURL), stringContent);
    string POSTresponse = await response.Content.ReadAsStringAsync();
    WriteLog(POSTresponse);

    //simplified output for debug
    if (POSTresponse.Contains("error") && POSTresponse.Contains("false")) {
        lblStatus.Text = "Error Sending to CL";
    } else {
        lblStatus.Text = "Successfully added to CL";
    }
}