控制'ZedGraphControl'从其创建的线程以外的线程访问

时间:2015-11-10 11:37:58

标签: c# asp.net multithreading zedgraph

我正在使用ZedGraph库,但是在网站而不是Web窗体应用程序上。快速介绍 - 应用程序从数据库获取数据,生成图形,将其保存为图像,然后在网页上显示图像。

我有一个GraphController类,基本上看起来像这样:

public class GraphController {

    private static GraphController instance;
    private static ZedGraph.ZedGraphControl graph;
    protected GraphController() { }

    public static GraphController Instance {
        get {
            if (instance == null){
                instance = new GraphController();
            }
            return instance;
        }
    }

    public string GenerateGraph(Dictionary<DateTime, float> graphData, DataRow details, string graphType) {
        if ((graph == null) || (graph.IsDisposed == false)) {
            graph = new ZedGraph.ZedGraphControl();
        }
        graph.GraphPane.Title.IsVisible = false;
        // function calls to generate graph. Graph object is referenced in these.
        return SaveGraphAsImage(0000, graphType);
    }

    private void AddGridLines() {
        // example of graph reference
        graph.GraphPane.XAxis.MajorGrid.IsVisible = true;
    }

    private string SaveGraphAsImage(string paramId, string graphType) {
        // Should deal with save location here 
        string location = HttpRuntime.AppDomainAppPath + "Graphs\\" + DateTime.Now.ToString("dd-MM-yyyy");
        string filename = DateTime.Now.ToString("dd-MM-yyyy-HH-mm-ss-") + graphType + "-" + paramId + ".png";

        if(System.IO.Directory.Exists(location) == false){
            System.IO.Directory.CreateDirectory(location);
        }
        graph.Refresh();

        try {
            using (graph) {
                string outputFileName = location + "\\" + filename;

                if (File.Exists(outputFileName) == false) {
                    Bitmap image = graph.GraphPane.GetImage(960, 660, 180);
                    image.Save(outputFileName, ImageFormat.Png);
                    image.Dispose();
                }
            }
            graph = null; // double check that it is removed.
            return "../Graphs/" + DateTime.Now.ToString("dd-MM-yyyy") + "/" + filename;
        }
        catch (Exception ex) {
            log("An error occured generating a graph. \n\n Error message: \n " + ex.Message + " \n\n Stack trace: \n " + ex.StackTrace);
            graph = null;
            return "#";
        }
    }
}

我尽可能地减少了它,但它应该显示如何创建,使用和删除ZedGraph对象。

我已经尝试过一些内存增强功能,尽可能地删除图形对象,并尝试using(){}进程以希望自动删除它,但欢迎进一步的建议。

我的目标是改善内存管理并减少这些错误。运行本地性能测试,我收到了很多Control 'ZedGraphControl' accessed from a thread other than the thread it was created on.错误。我对线程相对较新,所以我不确定a)它是否是这里需要的东西,或者b)可以做一些事情来禁用这种可能性,或者更好地管理图形对象以确保它总是在同一个线程中?

修改:首先从.aspx.cs页面调用此GraphController,其中包含以下内容:GraphController.GraphController.Instance.GenerateGraph(data, details, "graph-type");

第二次编辑:我重新编写了代码,没有将ZedGraphControl作为private static,而是在GenerateGraph内创建,然后在必要时传递。在60秒内对多达1,000个用户进行测试看起来已经消除了跨线程问题 - 这听起来有可能吗?

1 个答案:

答案 0 :(得分:0)

这里的问题是使用ZedGraph个变量。正如Henk Holterman在评论中指出的那样,只要应用程序进程处于活动状态,静态变量就会保持活动状态,并且与任何/所有用户请求分开。因此,通过将static对象作为ZedGraph变量,它意味着它可能仍然可用于多个请求,而不会被正确清除,遇到内存和跨线程问题。

解决方案是在第一个GenerateGraph函数中声明class Solution { public int solution(int A, int B, int K) { return (B==0) ? 1 : B/K + ( (A==0) ? 1 : (-1)*(A-1)/K); } } 实例,然后将相同的对象传递给使用它的每个其他函数。这可以确保它是整个过程中访问的同一线程中的同一对象。