使用外部事件打破一个循环

时间:2012-09-28 17:35:42

标签: c# .net while-loop workflow-foundation state-machine

我在Windows服务中有一个while循环,运行x次,并在从某个文件读取后启动x电话。现在,如果我想创建一个用户界面,它提供了一个停止电话呼叫的选项,即在完成之前打破while循环。我该怎么做?

假设我有一个功能。

DialCalls(x)
{
  for(int i= 0 ; i<x ; i++)
  {
    // Initiate call
  }
}

我可以在不同的线程中同时运行2,3个DialCalls函数,因为我在应用程序中也进行了线程处理。所以基本上什么是打破网页循环的最佳方式。

7 个答案:

答案 0 :(得分:6)

使用task取消(.net 4中的新内容):

[Fact]
public void StartAndCancel()
{
    var cancellationTokenSource = new CancellationTokenSource();
    var token = cancellationTokenSource.Token;
    var tasks = Enumerable.Repeat(0, 2)
                          .Select(i => Task.Run(() => Dial(token), token))
                          .ToArray(); // start dialing on two threads
    Thread.Sleep(200); // give the tasks time to start
    cancellationTokenSource.Cancel();
    Assert.Throws<AggregateException>(() => Task.WaitAll(tasks));
    Assert.True(tasks.All(t => t.Status == TaskStatus.Canceled));
}

public void Dial(CancellationToken token)
{
    while (true)
    {
        token.ThrowIfCancellationRequested();
        Console.WriteLine("Called from thread {0}", Thread.CurrentThread.ManagedThreadId);
        Thread.Sleep(50);
    }
}

http://blogs.msdn.com/b/csharpfaq/archive/2010/07/19/parallel-programming-task-cancellation.aspx 任务吞下异常所以有一些清理,可能是IDisposable? About task exceptions

答案 1 :(得分:4)

您可以在循环中编写if语句,以轮询外部事件的状态。

例如,你可以有一个标志:

bool break_out = false;

在外部事件中,将break_out标志设置为true:

break_out = true;

现在在你的循环中,你可以拥有:

DialCalls(x)
{
  for(int i= 0 ; i<x ; i++)
  {
    // Initiate call

    if (break_out) {
        break;
    }
  }
}

答案 2 :(得分:3)

创建支持取消的活动:

public event EventHandler<CancelEventArgs> Call;

如果订户存在并取消订阅,请不要致电:

while (true)
{
    var e = new System.ComponentModel.CancelEventArgs();
    if (Call != null)
    {
        Call(this, e);
    }
    if (!e.Cancel)
    {
        // Initiate call
    }
    else
    {
        break;
    }
}

答案 3 :(得分:1)

while (!_shouldStop) { /* work in progress */ }

并且在Stop()方法中,应该在同一个worker类中,bool变量必须设置为true。

此外,如果有任何服务员(如AutoResetEvent),则必须为.Set();

答案 4 :(得分:0)

通过使用变量告诉何时中断。

private bool _cancel;

void DialCalls(...)
{
    for (int i=0; i<x; i++)
    {
        ...
        if (_cancel) break;
        ....
    }
}

private void SomeEventHandler(object sender, EventArgs e)
{
    _cancel = true;
}

for (int i=0; i<x && !_cancel; i++)

答案 5 :(得分:0)

有一个易变的全局变量

public static volatile bool stop;    
stop=False;

DialCalls(x)
{
  for(int i= 0 ; i<x && !stop ; i++)
  {
    // Initiate call
  }
}

On Button Click => stop =True;

答案 6 :(得分:0)

在服务上实现一个端点,该端点接受切换全局/静态布尔(或其他某些)变量的消息,并使DialCalls内的循环在每次迭代开始时检查所述变量。它不会中断当前正在进行的任何电话,但我打赌你不希望服务在通话过程中挂断,只是不要转到下一个。这也会中断所有线程;只需确保变量本身是线程安全的(例如,使用volatile关键字)。