如何将此 C# 工作线程代码与共享数据变量的主线程解耦?
我如何修改下面的代码,以便更好地阅读代码:
a)将“workThreadMethod()”移动到它自己的类中
b)此工作线程类中没有任何代码引用主“程序”中的静态变量“
c 类)以上是主要的两个要求,但是我希望作为副作用,这将确保工作线程类方法的可测试性更容易测试,并且理想情况下可以通过 IOC 进行测试(例如Ninject)概念[如果这没有意义,那么出于问题的目的忽略这一点]
我不确定要解决的主要挑战是如何处理原始线程和原始线程之间的两个不同的共享变量。新线程(其中一个是新线程添加到的 ConcurrentQueue,另一个是原始线程用于指示新线程何时停止的 bool 变量)
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
namespace TestConsoleApp
{
class Program
{
// Main Thread uses to indicate to New Thread to stop
private static bool _shouldStop = false;
// New Thread uses to pass back result to Main Thread
private static long _results = 0;
// Main Thread passes ongoing updates to New Thread via this queue
private static ConcurrentQueue<long> _workQueue = new ConcurrentQueue<long>();
static void Main(string[] args)
{
var p = new Program();
p.TestThreads();
}
public void TestThreads()
{
_shouldStop = false;
var workThread = new Thread(workThreadMethod);
workThread.Start();
for (int i = 0; i < 100; i++)
{
_workQueue.Enqueue(i); // Add test data to queue
Debug.WriteLine("Queue : " + i);
Thread.Sleep(10);
}
Thread.Sleep(5000);
_shouldStop = true;
workThread.Join();
Debug.WriteLine("Finished TestThreads. Result = " + _results);
}
// Dequeuer Methods
private void workThreadMethod()
{
// Update Summary
while (!_shouldStop)
{
if (_workQueue.Count == 0)
{
Thread.Sleep(10);
}
else
{
long currentValue;
bool worked = _workQueue.TryDequeue(out currentValue);
if (worked)
{
_results += currentValue;
Debug.WriteLine("DeQueue: " + currentValue);
}
}
}
}
}
}
How could I modify the below code such that I could, for better readability in code:
a) move the "workThreadMethod()" into it's own class
b) not have any code in this worker thread class reference static variables from the main "Program" class
c) the above are the main two requirements, however I'm hoping that as a side effect this would then ensure that for testability the worker thread class methods would be easier to test and ideally lend itself to testing via the IOC (e.g. Ninject) concept [if this doesn't make sense then ignore this point for the purpose of the question]
The main challenge that I'm not sure about re solving is how to handle the two different shared variables between the originating thread & new thread (one of them a ConcurrentQueue which the new thread adds to, and the other a bool variable that the original thread uses to indicate to the new thread when to stop)
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Threading;
namespace TestConsoleApp
{
class Program
{
// Main Thread uses to indicate to New Thread to stop
private static bool _shouldStop = false;
// New Thread uses to pass back result to Main Thread
private static long _results = 0;
// Main Thread passes ongoing updates to New Thread via this queue
private static ConcurrentQueue<long> _workQueue = new ConcurrentQueue<long>();
static void Main(string[] args)
{
var p = new Program();
p.TestThreads();
}
public void TestThreads()
{
_shouldStop = false;
var workThread = new Thread(workThreadMethod);
workThread.Start();
for (int i = 0; i < 100; i++)
{
_workQueue.Enqueue(i); // Add test data to queue
Debug.WriteLine("Queue : " + i);
Thread.Sleep(10);
}
Thread.Sleep(5000);
_shouldStop = true;
workThread.Join();
Debug.WriteLine("Finished TestThreads. Result = " + _results);
}
// Dequeuer Methods
private void workThreadMethod()
{
// Update Summary
while (!_shouldStop)
{
if (_workQueue.Count == 0)
{
Thread.Sleep(10);
}
else
{
long currentValue;
bool worked = _workQueue.TryDequeue(out currentValue);
if (worked)
{
_results += currentValue;
Debug.WriteLine("DeQueue: " + currentValue);
}
}
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这是关注点分离的练习,最初我会将这个程序拆分为
工作提供者
和工作人员
。 Provider 负责队列和执行控制,而 Worker 负责计算。下面的代码是一个粗略的开始,但它应该可以帮助您继续。拆分这两个问题并使用构造函数注入已经在可测试性方面得到了回报,您现在可以在不涉及
Program
的情况下完全测试Worker
。注意:考虑到您的应用程序的进一步开发,我强烈建议您研究任务并行库。使用 TPL 等库使您能够利用多核处理器,而无需处理线程分配和工作调度的复杂性。 此处讨论了有关 TPL 的更多资源。
This is an exercise in separation of concerns, and initially I would split this program into a
work provider
andworker
. The provider is responsible for the queue and execution control while the worker should do calculation. The following code is a crude start but it should get you going.Splitting up the two concerns and using constructor injection already pays of in testability, you can now fully test
Worker
without involvingProgram
.Note: considering further development of your app I would strongly suggest that you look into the Task Parallel Library. Using a library such as the TPL enables you to take advantage of multi-core processors without having to deal with the complexities of thread allocation and work scheduling. More resources on the TPL is discussed here.