如何将此C#辅助线程代码与共享数据变量的主线程解耦?

如何将此C#辅助线程代码与共享数据变量的主线程解耦?,c#,.net,multithreading,dependency-injection,code-readability,C#,.net,Multithreading,Dependency Injection,Code Readability,如何修改下面的代码,以便更好地阅读代码: a) 将“workThreadMethod()”移动到它自己的类中 b) 此工作线程类中没有任何代码引用主“程序”类中的静态变量 c) 以上是主要的两个要求,但是我希望作为一个副作用,这将确保对于可测试性而言,工作线程类方法将更容易测试,并且最理想的情况是通过IOC(例如Ninject)概念进行测试[如果这没有意义,那么出于问题的目的忽略这一点] 我不确定重新解决的主要挑战是如何处理原始线程和新线程之间的两个不同共享变量(其中一个是新线程添加到的Conc

如何修改下面的代码,以便更好地阅读代码:

a) 将“workThreadMethod()”移动到它自己的类中

b) 此工作线程类中没有任何代码引用主“程序”类中的静态变量

c) 以上是主要的两个要求,但是我希望作为一个副作用,这将确保对于可测试性而言,工作线程类方法将更容易测试,并且最理想的情况是通过IOC(例如Ninject)概念进行测试[如果这没有意义,那么出于问题的目的忽略这一点]

我不确定重新解决的主要挑战是如何处理原始线程和新线程之间的两个不同共享变量(其中一个是新线程添加到的ConcurrentQueue,另一个是原始线程用来向新线程指示何时停止的bool变量)

使用System.Collections.Concurrent;
使用系统诊断;
使用系统线程;
命名空间TestConsoleApp
{
班级计划
{
//主线程用于指示新线程停止
私有静态bool_shouldStop=false;
//新线程用于将结果传回主线程
私有静态长_结果=0;
//主线程通过此队列将正在进行的更新传递给新线程
私有静态ConcurrentQueue_workQueue=新ConcurrentQueue();
静态void Main(字符串[]参数)
{
var p=新程序();
p、 TestThreads();
}
公共void TestThreads()
{
_shouldStop=false;
var workThread=新线程(workThreadMethod);
workThread.Start();
对于(int i=0;i<100;i++)
{
_workQueue.Enqueue(i);//将测试数据添加到队列
Debug.WriteLine(“队列:+i”);
睡眠(10);
}
睡眠(5000);
_shouldStop=true;
workThread.Join();
Debug.WriteLine(“Finished TestThreads.Result=“+\u results”);
}
//出列方法
私有void workThreadMethod()
{
//更新摘要
而(!\u应该停止)
{
如果(_workQueue.Count==0)
{
睡眠(10);
}
其他的
{
长电流值;
bool worked=\u workQueue.TryDequeue(out currentValue);
如果(工作)
{
_结果+=当前值;
Debug.WriteLine(“出列:+currentValue”);
}
}
}
}
}
}

这是一个分离关注点的练习,最初我会将此程序分为
工作提供者
工作者
。提供者负责队列和执行控制,而工作人员应执行计算。下面的代码是一个粗糙的开始,但它应该让你去

将这两个问题分开,并使用构造函数注入已经支付了可测试性的费用,您现在可以完全测试
工作者
,而不需要涉及
程序

注意:考虑进一步开发您的应用程序,我强烈建议您研究一下。使用TPL之类的库可以让您利用多核处理器,而不必处理线程分配和工作调度的复杂性。讨论了更多关于第三方物流的资源

公共接口IWorkProvider
{
布尔应该停止{get;}
长工;
}
公共类程序:IWorkProvider
{
//主线程用于指示新线程停止
私有静态bool_shouldStop=false;
//主线程通过此队列将正在进行的更新传递给新线程
私有静态ConcurrentQueue_workQueue=新ConcurrentQueue();
公共bool ShouldStop{get{return{u ShouldStop;}}
公共长工
{
长电流值;
bool worked=\u workQueue.TryDequeue(out currentValue);
如果(工作)
返回当前值;
返回null;
}
}
公社工人
{
私人长期业绩;
私有只读IWorkProvider\u workProvider;
公共长结果{get{return_Results;}}
公共工作者(IWorkProvider workProvider)
{
_工作提供者=工作提供者;
}
公共工作
{
//更新摘要
while(!\u workProvider.ShouldStop)
{
long?work=_workProvider.GetWork();
if(work.HasValue)
{
_结果+=工作价值;
Debug.WriteLine(“出列:+work.Value”);
}
其他的
{
睡眠(10);
}
}
}
}

您能提供一个客户机代码的入门示例吗?(我试着思考如何回答这个问题,但无法真正理解你想要什么)好主意鲁本-我现在更新了这个问题它现在值a+1,但现在太忙了,无法查看!谢谢你。我的下一步将尝试将这个概念转化为一些“并发”工作,我正在使用Quartz.Net,它已经有一个“IJob”接口,如果我可以。。。
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);
                    }
                }
            }
        }
    }
}
public interface IWorkProvider
{
    bool ShouldStop { get; }
    long? GetWork();
}

public class Program : IWorkProvider
{
    // Main Thread uses to indicate to New Thread to stop
    private static bool _shouldStop = false;

    // Main Thread passes ongoing updates to New Thread via this queue
    private static ConcurrentQueue<long> _workQueue = new ConcurrentQueue<long>();

    public bool ShouldStop { get { return _shouldStop; } }

    public long? GetWork()
    {
        long currentValue;
        bool worked = _workQueue.TryDequeue(out currentValue);
        if (worked)
            return currentValue;
        return null;
    }
}

public class Worker
{
    private long _results;
    private readonly IWorkProvider _workProvider;

    public long Results { get { return _results; }}

    public Worker(IWorkProvider workProvider)
    {
        _workProvider = workProvider;
    }

    public void DoWork()
    {
        // Update Summary
        while (!_workProvider.ShouldStop)
        {
            long? work = _workProvider.GetWork();
            if (work.HasValue)
            {
                _results += work.Value;
                Debug.WriteLine("DeQueue: " + work.Value);
            }
            else
            {
                Thread.Sleep(10);
            }
        }
    }

}