【问题标题】:Process async results in another thread在另一个线程中处理异步结果
【发布时间】:2012-07-06 21:34:32
【问题描述】:

我有一个 WinCE C# 应用程序,它轮询 (JAVA) 服务器以获取异步传入的消息。我想要实现的是我想轮询服务器,当返回结果时,将其排队,然后在另一个线程中处理该结果。我想将异步接收线程与进程线程隔离开来,因为在处理响应之后,我可能需要向服务器发送额外的 POST。

我现在拥有的是一个类似于这里显示的类

http://msdn.microsoft.com/en-us/library/86wf6409%28v=vs.80%29.aspx

用于向服务器发出异步请求并读取响应。我已经修改了该类以包含自定义超时,但这无关紧要。

在我的应用程序中发生的情况是,我开始在线程“pollingThread”中进行轮询,并从服务器获取响应。如果超时,响应将为空,否则我尝试处理响应。

我想将响应字符串发送给另一个可以处理它的线程,而我的 pollingThread 会返回继续轮询服务器。我不知道如何将响应发送到另一个线程。我知道如何在大窗口上使用 Monitor.Pulse,但不幸的是它在 NETCF 3.5 上不可用。

有什么见解吗?

谢谢

编辑:@Damon8or

我尝试使用 AutoReset 但由于某种原因,WaitOne() 没有意识到另一个线程已经 Set() 事件,因此它错过了通过的数据。这是我所拥有的:

AutoresetEvent _process 被声明为静态并且对两种方法都可见

ThreadStart processMethod= new ThreadStart(process);
processingThread= new Thread(processJSONMethod);
processingThread.IsBackground = true;
processingThread.Start();

ThreadStart startMethod = new ThreadStart(Poll);
connectionThread = new Thread(startMethod);
connectionThread.IsBackground = true;                    
connectionThread.Start();

在投票内部,我收到来自服务器的字符串后有_process.Set()。在处理方法中,我有:

while (_keepPolling)
{

_process.WaitOne();

string text= MyQueue.Dequeue();
Debug.WriteLine("Returned: " + text

}    

而且我没有看到正在打印的调试行。 poll 方法生成字符串并将其排队,然后返回轮询。

【问题讨论】:

  • 你的问题到底是什么?
  • 我想确保在另一个线程中处理结果时继续在我的 pollingThread 中进行轮询。在将结果推送到队列后,我不知道如何唤醒处理结果的线程

标签: c# multithreading asynchronous windows-ce


【解决方案1】:

您可以使用 AutoResetEvent 或 ManualResetEvent 向您的工作线程发出信号。下面是一个简单的例子。

    using System; 
    using System.Linq; 
    using System.Collections.Generic; 
    using System.Text; 
    using System.Threading; 

    namespace QueueDoodles 
    {
    class Program
    {
        public static readonly string[] data = { "a", "b", "c", "d", "e", "f", "g", "h" };

        static void Main(string[] args)
        {
            var running = true;
            var rand = new Random();
            var q = new Queue<string>();
            var qEvent = new ManualResetEvent(false);
            var pollThread = new Thread(new ThreadStart(delegate()
            {
                while (running)
                {
                    // Queue the next value
                    var value = data[rand.Next(data.Length)];
                    q.Enqueue(value);
                    Console.WriteLine("{0} queued {1}", Thread.CurrentThread.Name, value);

                    // Signal waiting thread
                    qEvent.Set();

                    // Simulate polling
                    Thread.Sleep(rand.Next(100));
                }
            }));
            pollThread.Name = "Poll Thread";

            var workerThread = new Thread(new ThreadStart(delegate()
            {
                while (running)
                {
                    // Wait on the queue
                    if (!qEvent.WaitOne())
                        break;
                    qEvent.Reset();

                    // Process the next queue item
                    var value = q.Dequeue();
                    Console.WriteLine("{0} queued {1}", Thread.CurrentThread.Name, value);
                }
            }));
            workerThread.Name = "Worker Thread";

            // Start the poll thread
            pollThread.Start();

            // Give it some time to fill queue
            Thread.Sleep(1000);

            // Start the worker thread
            workerThread.Start();

            // Wait for keyboard input
            Console.ReadLine();
            running = false;
            qEvent.Set();
        }
    }
}

【讨论】:

  • 请查看问题的编辑,我无法将其全部放在评论中。谢谢
  • 我添加了一个 Thread.Sleep(10);就在集合之后,它似乎帮助 WaitOne() 摆脱了等待。不知道该怎么做,但现在我遇到了另一个问题,即两个线程没有并行运行。处理线程似乎阻塞了connectionThread,即使它不应该。作为健全性检查,我将两个线程都作为后台线程。这有什么区别吗?谢谢
  • 我尝试在我的 QueueDoodle 代码中切换到 AutoResetEvent 并且效果很好 - 注释掉了 Reset() 调用,因为这是使用该类型自动完成的。事件或您的处理线程必须发生一些事情。我已经广泛使用了这些事件类并且它们总是有效的。一些要试验的东西... - 在您的处理线程中添加调试语句以查看它是否正在运行。 - 为 WaitOne(1000) 添加超时,并检查返回是否正在触发事件。 - 尝试 ManualResetEvent 看看它的行为是否不同。
  • 背景无关紧要。如果 thread.sleep(10) 有帮助,它可能来自轮询线程旋转,或者另一个占用 CPU 的线程。除非您想特别强制另一个线程在某个时候运行,否则您不应该需要睡眠。我删除了样本中的睡眠呼叫,它仍然运行良好。我知道这没什么用,但也许可以排除一些问题,然后集中精力让线程信号继续运行,然后开始添加处理并实际轮询回组合。
  • 是的,Autoreset 中 Set() 之后的 Thread.Sleep(10) 解决了我的问题。我相信布景发生在没有人等待的时候,然后当我在布景后立即去等待时,我没有什么可取的。感谢您的帮助!
【解决方案2】:

队列类是线程安全的,为什么不使用队列来对数据进行排队呢?

http://msdn.microsoft.com/en-us/library/system.collections.queue.aspx

【讨论】:

  • 另外,排队数据不是我的问题。我可以使用队列。我的问题是如何唤醒我的“处理器”线程来处理结果,同时确保我的 pollingThread 继续轮询
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-10
  • 1970-01-01
  • 2017-10-24
  • 1970-01-01
  • 1970-01-01
  • 2018-06-08
相关资源
最近更新 更多