8

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

假设我有一个函数。

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

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

4

7 回答 7

6

使用任务取消(.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? 关于任务异常

于 2012-09-28T17:40:13.167 回答
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;
    }
  }
}
于 2012-09-28T17:41:44.963 回答
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;
    }
}
于 2012-09-28T17:43:04.913 回答
1
while (!_shouldStop) { /* work in progress */ }

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

此外,如果有任何服务员(如AutoResetEvent),他们必须是.Set();

于 2012-09-28T17:45:43.947 回答
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++)
于 2012-09-28T17:43:14.120 回答
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;
于 2012-09-28T17:43:19.283 回答
0

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

于 2012-09-28T17:44:30.670 回答