c# - 如何在多线程环境中保持对象成员变量对线程私有(private)

标签 c# asp.net .net multithreading

我有一个多线程程序,它打开几个线程来查询外部 CRM,并将结果保存在内存中的 IDictionary 中,以加快系统速度。

我对多线程和临界区有点困惑。我希望我的类 QueryThreadProcess 有一个运行查询并管理启动和停止查询的线程。它有一个查询类型的对象,并将结果保存在列表中。

QueryManager 类将终止所有进程或启动所有进程,基本上是集合范围的方法。

我有一种感觉,QueryThreadProcess 的私有(private)成员在所有线程之间共享。我怎样才能使它们对每个线程都是私有(private)的,同时又能从外部类中单独杀死每个线程?

我不想锁定,因为我希望所有线程并行运行。

这是我的经理类:

public class QueryManager
{
    private IDictionary<int, QueryThreadProcess> _queries;

    public QueryManager()
    {
        _queries = new Dictionary<int, QueryThreadProcess>();
    }

    public void Start()
    {
        CreateQueryThreadsFromDb();
        StartAllThreads();
    }

    private void StartAllThreads()
    {
        if (_queries != null && _queries.Count > 0)
        {
            StopThreadsAndWaitForKill();

        }

        foreach (var query in _queries)
            query.Value.Start();
    }

    private void CreateQueryThreadsFromDb()
    {
        var queries = new QueryProvider().GetAllQueries();
        if (_queries != null && _queries.Count > 0)
        {
            StopThreadsAndWaitForKill();
            _queries.Clear();
        }

        foreach (var query in queries)
            _queries.Add(query.Id, new QueryThreadProcess(query));

    }

    private void StopThreadsAndWaitForKill()
    {
        KillAllThreads();
        while (!AreAllThreadsKilled()) { }
    }

    private void KillAllThreads()
    {
        foreach (var query in _queries)
            query.Value.Kill();
    }

    private bool AreAllThreadsKilled()
    {
        return _queries.All(query => query.Value.IsKilled);
    }

    public IList<User> GetQueryResultById(int id)
    {
        return _queries[id].Result;
    }
}

这是我的 QueryProcesses 类,它包含执行实际查询的线程:

using System.Collections.Generic;
using System.Threading;
using Intra.BLL.MessageProviders;
using Intra.BO;
using Intra.BO.Messages;


namespace Intra.BLL.QueryProcess
{
    internal class QueryThreadProcess
    {
        private readonly Thread _thread;
        private readonly Query _query;
        private bool _isStoppingQuery = false;
        private bool _isKilled = true;

        private IList<User> _result;
        private readonly object _objSync = new object();

        public QueryThreadProcess(Query query)
        {
            _query = query;
            _thread = new Thread(RetrieveQueries);
        }

        public void Start()
        {
            _isStoppingQuery = true;
            while (!_isKilled) { }
            _isStoppingQuery = false;
            _thread.Start();
        }

        private void RetrieveQueries()
        {
             const string BROKERNAME = "bla";

            _isKilled = false;
            while (!_isStoppingQuery)
            {
                Broker broker = new BrokerProvider().GetBrokerByName(BROKERNAME);
                var users = new QueryProvider().GetUserObjectsByQuery(_query, ParaTokenGenerator.GetBrokerAuthToken(broker));
                _result = users;
            }
            _isKilled = true;
        }

        public bool IsKilled
        {
            get { return _isKilled; }
        }


        public IList<User> Result
        {
            get
            {
                lock (_objSync)
                    return _result;
            }
        }

        public void Kill()
        {
            _isStoppingQuery = true;
        }
    }
}

最佳答案

它并没有真正回答你的问题,但它看起来像是一种使用 Task Parallel Library 的更现代的方法。 .NET 4 可以让您省去一些麻烦。不需要自己控制线程。看起来您可以将您的类重构为几行代码并摆脱所描述的问题。

关于c# - 如何在多线程环境中保持对象成员变量对线程私有(private),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8339342/

相关文章:

c# - Enum 的顺序为什么(以及如何)影响 ToString 值?

c# - 像 stackoverflow 一样的标签控件

c# - 使用 StackExchange.Redis 在 Azure Redis 缓存中存储自定义 .Net 对象

c# - 为用户控件内的列表框设置项目模板

c# - 无法保存使用 ASP.NET C# Web 窗体接收的 Razorpay Webhook 数据

asp.net - 正则表达式 asp.net.输入不能包含双空格

c# - 我可以在 C# 中重载 "cast from null"运算符吗?

c# - 在 ASP.NET 中使用 Ext JS

.net - .NET 中 OutOfMemoryException 的 try/catch block 的设计模式

c# - 调用 C# 方法,并使其在 10 秒后返回