gpt4 book ai didi

C# While 在工作线程中循环监听命令和响应

转载 作者:太空宇宙 更新时间:2023-11-03 20:29:26 33 4
gpt4 key购买 nike

问题概述:

我尝试使用一个线程(while..loop)来监听来自用户的命令。如果用户发送命令,它将在类(LoopingWorkerThread)中的全局变量中分配新值。

我不明白如果我不把线程休眠值设置为低于 10 毫秒,我就不会得到任何响应(它在 ListenCommand 方法中)。看起来全局参数在方法中被覆盖了“_CommandReceived”,可能是处理器运行速度太快而忽略了参数值的变化(“_CommandReceived”)。

如果有更好的机制欢迎评论。我已将其锁定在 ListenCommand while 循环中。

代码如下:

public class LoopingWorkerThread
{
/// <summary>
/// Local main thread for LoopingWorkerThread
/// </summary>
private Thread t;
/// <summary>
/// Local parameter to identify the LoopingWorkerThread Is On
/// </summary>
private bool _IsOn;
/// <summary>
/// Local parameter to store command received from user
/// </summary>
private int _CommandReceived;
/// <summary>
/// Local object to use for locking the LoopingWorker Thread
/// </summary>
private object _LockListenCommand = new object();
/// <summary>
/// Properties of LoopingWorker Thread Is On
/// </summary>
public bool IsOn
{
get { return _IsOn; }
set { _IsOn = value; }
}
/// <summary>
/// Property of storing the command received from user
/// </summary>
public int CommandReceived
{
get { return _CommandReceived; }
set { _CommandReceived = value; }
}
/// <summary>
/// Delegate for OnResponse Event Handler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public delegate void OnResponseHandler(object sender, ResponseArg e);
/// <summary>
/// Event of OnResponse
/// </summary>
public event OnResponseHandler OnResponse;
/// <summary>
/// Constructor of LoopingWorkerThread Class
/// </summary>
public LoopingWorkerThread()
{
_IsOn = false;
}
/// <summary>
/// Method of LoopingWorkerThread Function
/// </summary>
private void ListenCommand()
{
lock (_LockListenCommand)
while (_IsOn)
{
switch (_CommandReceived)
{
case 0:
// Ignore default command
break;
case 1:
FireOnResponse("Received cmd 1, response [Hello One]");
break;
case 2:
FireOnResponse("Received cmd 2, response [Hello Two]");
break;
default:
FireOnResponse("Error. Received unidentified command - " + _CommandReceived.ToString());
break;
}

//Console.WriteLine("ThreadProc: Cmd:[{0}] - Response:{1}", _CommandReceived.ToString(), ReaderResponse);

// Reset or Clear the Command Received
_CommandReceived = 0;

// If the sleep less than 10 millisecond, it always don't catch the
// command received which assigned to 1 or 2. Don't understand, or is there
// any better method.
**Thread.Sleep(10);**
}
}
/// <summary>
/// Function of firing response event back to user
/// </summary>
/// <param name="message"></param>
private void FireOnResponse(string message)
{
ResponseArg myarg = new ResponseArg(message);
if (OnResponse != null)
OnResponse(this, myarg);
}
/// <summary>
/// Method of starting the LoopingWorkerThread
/// </summary>
public void Start()
{
_IsOn = true;

FireOnResponse("Main thread: Started.");

// The constructor for the Thread class requires a ThreadStart
// delegate that represents the method to be executed on the
// thread. C# simplifies the creation of this delegate.
t = new Thread(new ThreadStart(ListenCommand));

// Start ThreadProc. Note that on a uniprocessor, the new
// thread does not get any processor time until the main thread
// is preempted or yields. Uncomment the Thread.Sleep that
// follows t.Start() to see the difference.
t.Start();

//Thread.Sleep(0);

FireOnResponse("Main thread: Call Start().");

}
/// <summary>
/// Method of stopping the LoopingWorkerThread
/// </summary>
public void Stop()
{
_IsOn = false;
t.Join();
//t.Abort();

FireOnResponse("LoopingWorker Thread is stopped.");
}
/// <summary>
/// Method of sending command to the LoopingWorkerThread
/// </summary>
/// <param name="readercmd"></param>
public void SendCommand(int readercmd)
{
_CommandReceived = readercmd;
}
}

最佳答案

您的代码有效是因为 Thread.Sleep produces the necessary memory barrier需要正确阅读 _commandReceived。如果您删除 Thread.Sleep 调用,那么您也删除了隐式内存屏障。显然,这不是一个值得依赖的好机制。

更重要的是,你的做法是错误的。您应该使用的是生产者-消费者模式。使用 BlockingCollection 类非常容易,因为它会在队列为空时在 Take 上阻止消费者。

public class Example
{
private BlockingCollection<int> commands = new BlockingCollection<int>();

public Example()
{
var thread = new Thread(Run);
thread.IsBackground = true;
thread.Start();
}

public void SendCommmand(int command)
{
commands.Add(command);
}

private void Run()
{
while (true)
{
int command = commands.Take();
ProcessCommand(command);
}
}

private void ProcessCommand(int command)
{
// Process the command here.
}
}

BlockingCollection 作为 Reactive Extensions 的一部分可用于 3.5下载。

关于C# While 在工作线程中循环监听命令和响应,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8337416/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com