vb.net - 在每个循环上等待一秒钟

标签 vb.net multithreading concurrency timer

我有想要它执行每个代码然后等待然后执行下一个代码的程序
这是我的代码:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim msg() As String = {"a", "b", "c", "e"}

    For Each item In msg
        MessageBox.Show(item)
    Next
End Sub

如果我想编写一个简单的伪代码,它将是这样的:
for each item in msg
    print(item)
    wait one second
next item

最佳答案

您需要将该方法标记为异步。

for each item in msg
    print(item)
    await Task.Delay(1000)//Await a second
next item

对于框架限制,如果您不能使用异步功能,则必须使用计时器或其他某种机制来实现。
Private Async Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim msg() As String = {"a", "b", "c", "e"}

    For Each item In msg
        MessageBox.Show(item)
        Await Task.Delay(1000)//Await a second
    Next
End Sub
Task.Delay(1000)将返回一个Task,它将在提供的毫秒数(在本例中为1000)后最终完成。我们正在等待(异步等待)该任务。要启用Await功能,您需要将该方法标记为Async

这将指导您async/await的工作方式。

对于.net 4.0,谁不能使用Bcl.Async包,下面的代码会有所帮助。
public class PeriodicEnumerator<T>
{
    private IEnumerable<T> sequence;
    private Action<T> action;
    private int period;
    private System.Threading.Timer timer;
    private SynchronizationContext synchronizationContext;
    private IEnumerator<T> enumerator;
    private TaskCompletionSource<object> completionSource = new TaskCompletionSource<object>();

    public PeriodicEnumerator(IEnumerable<T> sequence, Action<T> action, int period)
        : this(sequence, action, period, null)
    {

    }

    public PeriodicEnumerator(IEnumerable<T> sequence, Action<T> action, int period, SynchronizationContext synchronizationContext)
    {
        this.sequence = sequence;
        this.action = action;
        this.period = period;
        this.synchronizationContext = synchronizationContext;

        this.timer = new System.Threading.Timer(TimerCallback);
    }

    public Task Enumerate()
    {
        if (this.enumerator != null)
        {
            throw new InvalidOperationException("Enumeration already started");
            //To avoid multiple enumerations, better create new instance
        }
        enumerator = sequence.GetEnumerator();
        timer.Change(0, Timeout.Infinite);

        return completionSource.Task;
    }

    private void TimerCallback(object state)
    {
        if (!enumerator.MoveNext())
        {
            completionSource.SetResult(null);
            timer.Dispose();
            return;
        }
        try
        {
            T current = enumerator.Current;
            if (synchronizationContext != null)
            {
                synchronizationContext.Send((x) => action(current), null);
            }
            else
            {
                action(current);
            }
            timer.Change(period, Timeout.Infinite);
        }
        catch (Exception ex)
        {
            completionSource.SetException(ex);
            timer.Dispose();
        }
    }
}

用例:
static void ConsoleAppSample()
{
    var periodicEnumerator = new PeriodicEnumerator<int>(Enumerable.Range(1, 5), (x) => Console.WriteLine(x), 1000);
    Task enumerationTask = periodicEnumerator.Enumerate();
    enumerationTask.Wait();//Optionally wait for completion
    Console.WriteLine("Completed");
    Console.Read();
}

static void SynchronizationContextSample()//applicable for any UI apps
{
    var periodicEnumerator = new PeriodicEnumerator<int>(Enumerable.Range(1, 5), (x) => textbox.Text = x.ToString(), 1000,SynchronizationContext.Current);
    Task enumerationTask = periodicEnumerator.Enumerate();
    Console.WriteLine("Completed");
    Console.Read();
}

代码非常简单,我相信不需要任何解释:)如果有任何疑问,请删除注释。
  • 注意Enumerate方法返回一个任务,因此您可以等待
    在它上面,或者附上延续或其他内容。 (您可以添加
    取消功能等)。
  • 还支持GUI应用程序以确保触发了回调
    UI线程(提供SynchronizationContext)(如果提供),以便您
    可以轻松地在回调中更新UI。

  • P.S:对C#代码表示歉意,基本上是C#家伙,要在Vb.Net中编写代码,我需要几天的时间:

    关于vb.net - 在每个循环上等待一秒钟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22112036/

    相关文章:

    mysql - DataGridView选择多行,检查每一行

    vb.net - 使用 vb.net 中的文件路径以编程方式终止应用程序

    asp.net - 如何将表格行添加到 GridView 的标题部分?

    python - 您可以在不写入硬盘的情况下创建临时文件吗

    c++ - Boost Asio延迟写入tcp套接字

    java - volatile 实际上是如何工作的?

    swift - 当保存在后台异步完成时,我应该如何保证嵌套上下文中不同线程的获取结果是最新的?

    vb.net - 线程 System.NullReferenceException

    c - 线程中的时间间隔

    c# - thread.join() 也会阻塞其他客户端吗?