一个While循环线程

5

我一直在尝试编写代码,在while循环中使用UdpClient向服务器发送数据,具体来说是一个alive数据包。

 static void doSend(string ip, int port)
    {
        while (isSending)
        {
            _sockMain = new UdpClient(ip, port);
            // Code for datagram here, took it out
            _sockMain.Send(arr_bData, arr_bData.Length);
        }
    }

但是当我调用“Stop”方法时,它会陷入一个常量循环中而无法退出。我如何将while循环放入一个线程中?这样我就可以在停止时中止线程,取消循环。


1
如果您从未更改变量 isSending,则永远无法从循环中退出。 - Gianni B.
是的,当我按下一个按钮时 isSending = false 但它就是不退出。 - Daaksin
那么问题可能不在你的循环中,而是在数据报代码的某个地方。 - AmazingDreams
你需要发布更多的代码,这还不够。 - Alan
也许它是,AmazingDreams... 而且,对不起,Alan... - Daaksin
看起来你的 isSending 变量作用域有问题。请发布更多代码(比如你在哪里声明了 isSending)。并且尝试在点击按钮后调试变量的值。 - Gianni B.
4个回答

9

出现程序“假死”的原因是你的doSend方法在UI线程上运行。你可以使用以下类来使其在单独的线程上运行,或者你可以使用BackgroundWorkerClass

public class DataSender
    {
        public DataSender(string ip, int port)
        {
            IP = ip;
            Port = port;
        }

        private string IP;
        private int Port;
        System.Threading.Thread sender;
        private bool issending = false;

        public void StartSending()
        {
            if (issending)
            {
                // it is already started sending. throw an exception or do something.
            }
            issending = true;
            sender = new System.Threading.Thread(SendData);
            sender.IsBackground = true;
            sender.Start();
        }

        public void StopSending()
        {
            issending = false;
            if (sender.Join(200) == false)
            {
                sender.Abort();
            }
            sender = null;
        }

        private void SendData()
        {
            System.Net.Sockets.UdpClient _sockMain = new System.Net.Sockets.UdpClient(IP, Port);
            while (issending)
            {
                // Define and assign arr_bData somewhere in class
                _sockMain.Send(arr_bData, arr_bData.Length);
            }
        }
    }

我喜欢这个!谢谢Taner! - Daaksin
1
太糟糕了!在任何答案中都没有提到 volatile - Alexander Petrov
@AlexanderPetrov 可能是因为 volatile 关键字是后来才添加的! - Laurent

4

您可以使用后台工作线程http://www.dotnetperls.com/backgroundworker,并在dowork()内放置while循环。 您可以通过使用CancelAsync()停止代码,并设置backgroundWorker1.WorkerSupportsCancellation == true

BackgroundWorker bw = new BackgroundWorker();
          if (bw.IsBusy != true)
          {
              bw.RunWorkerAsync();

          }

          private void bw_DoWork(object sender, DoWorkEventArgs e)
          {
              // Run your while loop here and return result.
              result = // your time consuming function (while loop)
          }

          // when you click on some cancel button  
           bw.CancelAsync();

2
这种方式行不通。您需要设置 WorkerSupportsCancellation 并在循环内检查 CancellationPending。完整的示例可以在 MSDN 上找到。 - Oliver

1
static bool _isSending;

static void doSend(string ip, int port)
{
    _isSending = true;

    while (_isSending)
    {
        _sockMain = new UdpClient(ip, port);
        // ...
        _sockMain.Send(arr_bData, arr_bData.Length);
    }
}

static void Stop()
{
    // set flag for exiting loop here
    _isSending = false;    
}

同时考虑使用 PascalCase 命名你的方法,例如 DoSend(甚至更好的是 StartSending),StopSending


谢谢您,但它卡住了?程序仍然会接收到数据。 - Daaksin
因为你在循环中发送。当前发送完成后,下一个发送将不会发生。 - Sergey Berezovskiy

0

使用 BREAK 语句怎么样?


请检查以下链接:http://msdn.microsoft.com/zh-cn/library/2aeyhxcd(v=vs.71).aspx,http://www.dotnetperls.com/while。Break语句可用于终止while循环。 - TechDo
只有在点击按钮时,我才想退出它,否则它必须继续运行? - Daaksin
然后定义一个按钮点击事件,该事件会更改一个布尔变量isSending。 - AmazingDreams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接