循环函数中的异步计时器不停止主线程

时间:2017-03-16 11:55:41

标签: c#

我使用"开始"创建了WPF表单。按钮,这个按钮是" StartMacros"功能

当我点击"开始"按钮我想运行一个循环并每隔10秒打开一个firefox浏览器,而不停止MAIN线程,所以我可以创建另一个" Pause"按钮或"取消"按钮

现在一切正常,但循环没有延迟,我该如何创建呢? "等待Task.Delay((10000));"没有造成延迟..

try
{
    int i = 0;
    Task t1 = Task.Factory.StartNew(() =>
        {
            i = 2 * 4;
        });

    Task<int> t2 = Task.Factory.StartNew(() =>
        {
            int a = 0;
            int b = 100 / a;
            return 0;
        });

    Task[] tasks = new Task[] { t1, t2 };
    Task.WaitAny(tasks);
    //Task.WaitAll(tasks);// Working

}
catch (AggregateException ae)
{
    var message = ae.InnerException.Message;
    Console.WriteLine(message);
}
Console.ReadLine();

3 个答案:

答案 0 :(得分:2)

您只需一种方法即可完成此任务:

private async void StartMacros(object sender, RoutedEventArgs e)
{
    for (int profileNumber = 1; profileNumber <= 10; profileNumber++)
    {
        OpenBrowser(profileNumber);
        await Task.Delay(10000);
    }
}

注意,我已在方法中添加了async关键字。

这里发生的事情是微妙的。您的代码未按预期运行的原因是因为您StartMacros正在同步调用AsyncTimerLoop方法 。它调用的方法然后在主线程上快速循环多次。在每次循环迭代中,它调用你的OpenBrowser(仍然在主线程上),然后等待对Task.Delay的调用(实际上返回一个等待的Task,但你的代码不做任何与之相关的东西 - 它只会把它们扔掉)。由于您使用await关键字调用它,它在另一个线程上执行此操作 - 每个循环迭代一个线程 - 并且继续在主线程上循环,在每个循环中调用OpenBrowser,直到它完成循环并退出函数;这一切发生得非常迅速。对Task.Delay的调用不做任何事情,除了在另一个线程上延迟十秒然后退出。他们基本没用。

现在,您可以这样做:

private async void StartMacros(object sender, RoutedEventArgs e)
{
    await AsyncTimerLoop();
}

public async Task AsyncTimerLoop()
{
    for (int profileNumber = 1; profileNumber <= 10; profileNumber++)
    {
        OpenBrowser(profileNumber);
        await Task.Delay((10000));
    }
}

请注意,我已将async关键字添加到StartMacros,就像我上面的代码一样,我也正在等待对{{1}的调用}。为了做到这一点,我必须将AsyncTimerLoop的返回类型更改为AsyncTimerLoop,使其等待。现在,当您运行代码时,它等待在单独线程上对Task的整个调用,立即将控制权返回到AsyncTimerLoop,立即退出,以便应用程序事件循环可以恢复,使应用程序保持响应。同时,整个StartMacros任务在一个单独的线程上运行,在每次循环迭代期间等待十秒,因此在每次调用AsyncTimerLoop之间等待十秒。

我的代码类似于你的这个修改版本,它更简洁。

答案 1 :(得分:0)

试试此代码,使用

 var task = Task.Run(() => OpenBrowser(profileNumber));
    if (task.Wait(TimeSpan.FromSeconds(10000)))
    {
       return task.Result;   
    }   

将System.Threading.Tasks命名空间添加到代码中以访问任务并行库。

 using System.Threading.Tasks;


 public void StartMacros(object sender, RoutedEventArgs e)
 {
    AsyncTimerLoop();
 }

public async void AsyncTimerLoop()
{
    for (int profileNumber = 1; profileNumber <= 10; profileNumber++)
    {
        var task = Task.Run(() => OpenBrowser(profileNumber));
        if (task.Wait(TimeSpan.FromSeconds(10000)))
        {
          return task.Result;   
        } 
    }
}
public void OpenBrowser(int profileNumber)
{
    System.Diagnostics.Process.Start("firefox.exe", "-P " + profileNumber + " -no-remote imacros://run/?m=\"" + ImacroFilePath + "\"");
}

答案 2 :(得分:0)

计时器不会更容易吗?

308238445d5c
74435614a991
f2f59eb61aae