C# 多线程设计

C# 多线程设计,c#,.net,multithreading,parallel-processing,C#,.net,Multithreading,Parallel Processing,我有一个程序,将存储一些服务器的网络活动数据。为了提高速度,我将设计应用程序,在单独的线程中发出每个请求,并将结果放入一个通用字典中,其中键是服务器id,对象是结果类 但是,来自服务器的响应应每10分钟保存到DB。我不知道我是否有解决这个问题的好办法。因此,一些投入将是伟大的 我想到的是锁定结果字典,对结果进行深度克隆,并开始在另一个线程中分析结果,该线程刚刚将结果放入数据库中 如何最大限度地减少来自请求线程的阻塞,以便它们可以尽快开始添加新结果,但仍然可以从字典中读取内容?您可以通过使用。使用

我有一个程序,将存储一些服务器的网络活动数据。为了提高速度,我将设计应用程序,在单独的线程中发出每个请求,并将结果放入一个通用字典中,其中键是服务器id,对象是结果类

但是,来自服务器的响应应每10分钟保存到DB。我不知道我是否有解决这个问题的好办法。因此,一些投入将是伟大的

我想到的是锁定结果字典,对结果进行深度克隆,并开始在另一个线程中分析结果,该线程刚刚将结果放入数据库中


如何最大限度地减少来自
请求线程的阻塞
,以便它们可以尽快开始添加新结果,但仍然可以从字典中读取内容?

您可以通过使用。使用基于计时器的事件每隔10分钟运行一个线程,该事件将检查字典的内容并将当前计数项保存到数据库中,删除当前计数项,然后开始对保存的内容进行分析

// myCD is your concurrent dictionary
// every 10 mins
var myCDClone = myCD.MemberwiseClone();
// save to DB using myCDClone 
// using myCDClone.Keys delete everything saved up from myCD
// myCDClone.Clear();

通过使用,可以避免锁定字典。使用基于计时器的事件每隔10分钟运行一个线程,该事件将检查字典的内容并将当前计数项保存到数据库中,删除当前计数项,然后开始对保存的内容进行分析

// myCD is your concurrent dictionary
// every 10 mins
var myCDClone = myCD.MemberwiseClone();
// save to DB using myCDClone 
// using myCDClone.Keys delete everything saved up from myCD
// myCDClone.Clear();

其思想是在持久化逻辑触发时将当前状态放在一边,同时将新输入定向到新的存储中。这是此任务的基本模式:

class PeriodicPersist{

    // Map must be volatile, persist may look at a stale copy
    private volatile Map<String, String> keyToResultMap = new HashMap<String, String>();

    public  void newResult(String key, String result) {
        synchronized(keyToResultMap) {  // Will not enter if in the beginning of persist
            keyToResultMap.put(key,result);
        }
    }

    public void persist(){
        Map<String, String> tempMap;
        synchronized (keyToResultMap) { // will not enter if a new result is being added just now.
            if(keyToResultMap.size() == 0) {
                return;
            }

            tempMap = keyToResultMap;
            keyToResultMap = new HashMap<String, String>();
        }

        // download freshMap to the DB OUTSIDE the lock
    }
}
class PeriodicPersist{
//映射必须是易变的,持久化可能会查看过时的副本
private volatile Map keyToResultMap=new HashMap();
public void newResult(字符串键、字符串结果){
已同步(keyToResultMap){//如果在“持久化”的开头,则不会输入
keyToResultMap.put(键,结果);
}
}
公共图书馆{
Map tempMap;
synchronized(keyToResultMap){//如果刚刚添加新结果,则不会输入。
if(keyToResultMap.size()==0){
返回;
}
tempMap=keyToResultMap;
keyToResultMap=newhashmap();
}
//将freshMap下载到锁外的DB
}
}

想法是在持久化逻辑触发时将当前状态放在一边,同时将新输入定向到新的存储中。这是此任务的基本模式:

class PeriodicPersist{

    // Map must be volatile, persist may look at a stale copy
    private volatile Map<String, String> keyToResultMap = new HashMap<String, String>();

    public  void newResult(String key, String result) {
        synchronized(keyToResultMap) {  // Will not enter if in the beginning of persist
            keyToResultMap.put(key,result);
        }
    }

    public void persist(){
        Map<String, String> tempMap;
        synchronized (keyToResultMap) { // will not enter if a new result is being added just now.
            if(keyToResultMap.size() == 0) {
                return;
            }

            tempMap = keyToResultMap;
            keyToResultMap = new HashMap<String, String>();
        }

        // download freshMap to the DB OUTSIDE the lock
    }
}
class PeriodicPersist{
//映射必须是易变的,持久化可能会查看过时的副本
private volatile Map keyToResultMap=new HashMap();
public void newResult(字符串键、字符串结果){
已同步(keyToResultMap){//如果在“持久化”的开头,则不会输入
keyToResultMap.put(键,结果);
}
}
公共图书馆{
Map tempMap;
synchronized(keyToResultMap){//如果刚刚添加新结果,则不会输入。
if(keyToResultMap.size()==0){
返回;
}
tempMap=keyToResultMap;
keyToResultMap=newhashmap();
}
//将freshMap下载到锁外的DB
}
}

只要换一本新字典就行了。很快,别忘了锁。把字典换成新的就行了。非常快,别忘了锁定。即使CD中有一个非线程安全列表作为对象,也可以克隆它吗?ConcurrentDictionary如果列表在同一时刻被修改怎么办?否由于并发性没有渗透到所有keyvaluepair对象,只是字典访问。即使CD中有一个非线程安全的列表作为对象,是否可以克隆它?ConcurrentDictionary如果列表在同一时刻被修改怎么办?不,由于并发性没有渗透到所有keyvaluepair对象,只是字典访问。