在我的后台辅助角色完全使用垃圾回收之前,是否在我的静态属性上发生垃圾回收

本文关键字:我的 静态 是否 属性 角色 后台 | 更新日期: 2023-09-27 18:35:52

我在处理大文件导入的网页中有一个后台工作线程。 我有一个静态属性,其中包含一个值字典,我需要我的后台工作人员访问该字典。 为了防止垃圾回收出现问题,我在将字典传递到后台工作线程时将其字符串化。 问题是,大约 20 次中有 1 次,字典在字符串化之前似乎被垃圾回收了。

static readonly Dictionary<int, int> myDictionary = new Dictionary<int, int>();

单击按钮时,我解雇后台工作人员

假设后代,我已经用值列表填充了字典,这些值在工人排队时就存在。

protected void OnProcessClickHandler(object sender, EventArgs e)
{
    ThreadPool.QueueUserWorkItem(ProcessInBackground, new object[] { 
        DictionaryIntIntToCsv(myDictionary)
        });
}

后台进程示例

private void ProcessInBackground(object state)
{
    object[] parms = state as object[];
    if (parms != null && parms.Length > 0)
    {
        var MyNewDictionary = DictionaryIntIntFromCsv(parms[0] as string);
        //... Doing something with the Dictionary
    }
}

以下是我用来串化字典的一些辅助方法。 您可以忽略这些,除非您认为它们与手头的问题有关。

public static Dictionary<int, int> DictionaryIntIntFromCsv(string csv)
{
        var dictionary = new Dictionary<int, int>();
        foreach (var pair in csv.Split(','))
        {
            var arrNameValue = pair.Split(':');
            if (arrNameValue.Count() != 2) continue;
            var key = 0;
            var val = 0;
            int.TryParse(arrNameValue[0], out key);
            int.TryParse(arrNameValue[1], out val);
            if (key > 0 && val > 0)
            {
                dictionary.Add(key, val);
            }
        }
        return dictionary;
}
public static string DictionaryIntIntToCsv(Dictionary<int, int> dictionary)
{
        var str = "";
        foreach (var key in dictionary.Keys)
        {
            var value = 0;
            dictionary.TryGetValue(key, out value);
            if (key == 0 || value == 0) continue;
            var item = key + ":" + value;
            str += (item + ",");
        }
        return str;
}

我知道垃圾回收有问题。 我的理论是有时主线程完成,垃圾回收在后台工作者有机会字符串化字典之前运行。 如果我在对后台工作线程排队之前字符串化字典,我可以避免垃圾回收问题,我是否正确? 这样:

protected void OnProcessClickHandler(object sender, EventArgs e)
{
    var MyString = DictionaryIntIntToCsv(MyDictionary);
    ThreadPool.QueueUserWorkItem(ProcessInBackground, new object[] { 
        MyString
        });
}

注意:该页面是交互式的,在触发后台辅助角色之前会执行多次回发。

在我的后台辅助角色完全使用垃圾回收之前,是否在我的静态属性上发生垃圾回收

这个问题确实有很多错误信息和奇怪的实现,以至于如果不进一步澄清就无法回答。

是什么让你相信一旦你"串化"了字典,它就会被收集起来?您实际上如何处理ProcessInBackground()方法中的字典值?处理实际上是否比无缘无故地在string之间序列化和反序列化字典更昂贵?如果是这样,为什么还要使用后台工作线程?为什么字符串在对象数组中传递,而不仅仅是字符串本身?进一步说到这一点,为什么字典要被序列化,有什么好的理由不能直接作为state参数传入吗?

您可能正在加载页面时初始化该属性。 对属性的引用与页面加载时存在的页面实例相关联。 在服务器将初始页面交付给您后,该类符合垃圾回收条件。

我相信您看到的是用户在页面上执行回发所需的时间与服务器收集类的第一个实例所需的时间之间的竞争条件。

如果该属性是非静态的,则回发时将不存在这些值。 但是,由于它是一个静态属性,因此它将存在于内存中,直到垃圾回收器清理它。

在这里,您可以使用字典创建一个局部变量:

if (parms != null && parms.Length > 0)
{
    var MyNewDictionary = DictionaryIntIntFromCsv(parms[0] as string);
}

以上内容不会以任何方式影响以下内容。 在代码中的其他任何地方,您都没有填充静态字段MyDictionary

上面的

局部变量与下面的静态字段完全分开,因此上面的赋值不会以任何方式影响下面的属性:

static readonly Dictionary<int, int> MyDictionary = new Dictionary<int, int>();