Асинхронные и ожидающие задачи становятся пропущенными - PullRequest
0 голосов
/ 28 июня 2018

Я получаю сообщение "Потому что этот звонок не ожидается ..." на

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 голосов
/ 28 июня 2018

Ссылка Асинхронное / ожидание - лучшие практики асинхронного программирования , обработчики событий позволяют 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";
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...