在每个循环上等待一秒钟

时间:2014-03-01 08:28:44

标签: 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

3 个答案:

答案 0 :(得分:4)

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

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 pack以下代码将有所帮助。

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();
        }
    }
}

USECASE:

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();
}

代码非常简单,我相信不需要解释:)如果有任何删除评论。

  1. 请注意Enumerate方法返回任务,以便您可以等待 在它上面,或附加延续或其他什么。 (你可以补充一下 取消功能等)。
  2. 还支持GUI应用程序,以确保触发回调 UI线程(给定SynchronizationContext)如果提供了任何,那么你 可以轻松更新回调中的UI。
  3. P.S:为c#代码道歉,基本上是c#guy,我需要几天的代码才能在Vb.Net中编码:p

答案 1 :(得分:2)

您可以通过使线程休眠几秒钟来完成此操作,如下所示

System.Threading.Thread.Sleep(1000); 

答案 2 :(得分:1)

我在我的代码中使用了线程,因为睡眠会挂起应用程序。

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim thread As New System.Threading.Thread(AddressOf ShowMessage)
    thread.IsBackground = True
    thread.Start()
End Sub

Private Sub ShowMessage()
    Dim msg() As String = {"a", "b", "c", "e"}
    For each item As String In msg
        MessageBox.Show(item)
        System.Threading.Thread.Sleep(1000)
    Next
End Sub