winforms For循环仅使用ExecuteScriptAsync方法运行一次

wa7juj8i  于 2022-11-17  发布在  其他
关注(0)|答案(2)|浏览(150)

环境是C#和WinForms。我试图运行一个程序,将创建一个图像下载元素在一个已经创建的网站。我使用WebView 2作为浏览器。我改变了for循环2迭代只是为了调试这个问题。我可以下载1图像成功,但我的结果是在1迭代最大。感谢任何帮助!下面是代码给我的问题:

async void multiplePics (int column) => await webView2.ExecuteScriptAsync("" +
                "var downloadElement=document.createElement('a'); " +
                "downloadElement.setAttribute('download',''); " +
                "downloadElement.href= document.getElementsByClassName('slick-slide slick-cloned')[" +  column + "].getElementsByClassName('item')[0].getAttribute('href'); " +
                "document.body.appendChild(downloadElement); " +
                "downloadElement.click();" +
                "downloadElement.remove();  " +
                "");

            for (int i = 0; i <= 1; i++)
            {
                Debug.WriteLine(i);
                multiplePics( i);
            }

已尝试:

async private void button5_Click(object sender, EventArgs e)
        {
         void multiplePics(int column) {
                //webView2.ExecuteScriptAsync( "javascript");
                }

         for (int i = 0; i <= 1; i++)
               {await multiplePics(i);}
        }

也尝试过:

private void button5_Click(object sender, EventArgs e)
        {
         Task<string> multiplePics(int column) {
                //return webView2.ExecuteScriptAsync( "javascript");
                }

         Task.Run( ()=>{ return multiplePics(0);} );
         Task.Run( ()=>{ return multiplePics(1);} );
//tried GetAwaiter() along with GetResult() also
        }

另一种尝试:

private async void button5_Click(object sender, EventArgs e)
        {
     //tried public & private async Task multiplePics with no success
     //async Task multiplePics had no errors but had the same result
          private async Task multiplePics(int column) => 
                await webView2.ExecuteScriptAsync("" +
                 "var downloadElement=document.createElement('a'); " +
                 "downloadElement.setAttribute('download',''); " +
                 "downloadElement.href= document.getElementsByClassName('slick-slide slick-cloned')[" + column + "].getElementsByClassName('item')[0].getAttribute('href'); " +
                 "document.body.appendChild(downloadElement); " +
                 "downloadElement.click();" +
                 "downloadElement.remove();  " +
                 "");

                for (int i = 0; i <= 3; i++) 
                   {
                      await multiplePics(i);
                   }

        }
zpqajqem

zpqajqem1#

第一件事是更新multiplePics的签名以返回Task

private async Task multiplePics (int column) => await webView2.ExecuteScriptAsync(...);

然后,您可以在签章中包含async,从事件行程常式使用方法:

// event handlers use async void, not async Task
private async void button5_Click(object sender, EventArgs e)

最后,您现在可以在事件行程常式中使用multiplePics方法:

private async void button5_Click(object sender, EventArgs e)
{
    for (int i = 0; i <= 1; i++)
    {
        await multiplePics(i);
    }
}

但是,鉴于上面的循环只定义为迭代一次两次,更新循环的次数;现在假设为3:

private async void button5_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 3; i++) // 3 loops
    {
        await multiplePics(i);
    }
}

假设上面的程序现在将连续下载3个图像,您最终会希望并行下载它们,而不会阻塞UI。
最后,如果上述方法仍然不起作用,您需要提供更多有关这意味着什么的信息:“* 但我的结果在1次迭代时达到最大值 *"。

编辑

有关使用async/await的更多信息,我建议您至少从以下帖子/文章开始,这些帖子/文章详细介绍了何时返回Task以及何时可以接受void(提示,仅针对事件)。
一位C#语言设计人员编写的SO答案:What's the difference between returning void and returning a Task?
MSDN文章由最了解async/await的开发人员之一撰写:Async/Await - Best Practices in Asynchronous Programming
MSDN文章的同一作者回答了一个SO问题:Why exactly is void async bad?
还有其他几篇文章和SO问答将对该主题进行更深入的探讨;对相关关键词进行一点搜索会有很大帮助,例如:“异步void与异步任务”

编辑#2

根据我的意见,使用下面的代码,该代码直接取自最新的示例,但为结果添加了调试写入。

private async void button5_Click(object sender, EventArgs e)
{
    for (int i = 0; i < 3; i++) 
    {
       await multiplePics(i);
    }
}

private async Task multiplePics(int column)
{
    var result = await webView2.ExecuteScriptAsync("" +
         "var downloadElement=document.createElement('a'); " +
         "downloadElement.setAttribute('download',''); " +
         "downloadElement.href=document.getElementsByClassName('slick-slide slick-cloned')[" + column + "].getElementsByClassName('item')[0].getAttribute('href'); " +
         "document.body.appendChild(downloadElement); " +
         "downloadElement.click();" +
         "downloadElement.remove();" +
         "");
         
    Debug.WriteLine($"Col {column} result: {result}");
}
w6mmgewl

w6mmgewl2#

尽管@丹尼尔的回答是正确的,但如果确实有多个下载要执行,您始终可以执行以下操作:
创建布尔值的任务列表;

List<Task<bool>> lstImageTasks = new List<Task<bool>>();

将void“multiplePics”更改为bool函数,然后使用以下代码:

for (int i = 0; i <= 1; i++)
{
    lstImageTasks.Add(multiplePics(i));
}

while (lstImageTasks.Any())
{
    Task<bol> task = await Task.WhenAny(lstImageTasks);
    var resTask = task.Result;
    if (resTask != null)
    {
        if (resTask)
        {
            //SUCESS! do whatever you want... (implement log, Console.WriteLine(), ...)
        }
        else
        {
            //UPS...! do whatever you want... (implement log, Console.WriteLine(), ...)
        }
    }
    lstFeedBackTasks.Remove(task);
}

相关问题