简体   繁体   English

从不是在其上创建线程的线程访问控件“ ZedGraphControl”

[英]Control 'ZedGraphControl' accessed from a thread other than the thread it was created on

I'm using the ZedGraph library, but on a website rather than Web Forms application. 我正在使用ZedGraph库,但使用的是网站而不是Web Forms应用程序。 Quick intro - the app gets data from a database, generates a graph, saves it as an image and then displays the image on a web page. 快速介绍-该应用程序从数据库获取数据,生成图形,将其另存为图像,然后在网页上显示该图像。

I have a GraphController class, which basically looks like this: 我有一个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 "#";
        }
    }
}

I've reduced it as much as possible, but it should show how the ZedGraph object is created, used and removed. 我已尽可能减少它,但它应显示ZedGraph对象是​​如何创建,使用和删除的。

I've already tried some memory enhancements, getting rid of the graph object where possible, and trying the using(){} process to hopefully automatically remove it, but would welcome further suggestions. 我已经尝试了一些内存增强功能,在可能的情况下摆脱了graph对象,并尝试了using(){}进程以希望自动将其删除,但是欢迎您提出进一步的建议。

My aim here is to improve memory management and reduce these errors. 我的目的是改善内存管理并减少这些错误。 Running local performance tests, I get quite a few Control 'ZedGraphControl' accessed from a thread other than the thread it was created on. 通过运行本地性能测试,我Control 'ZedGraphControl' accessed from a thread other than the thread it was created on. errors. 错误。 I'm relatively new to threading, so I'm not sure if a) it is something that is needed here, or b) there's something that can be done to disable the possibility, or a better management of the graph object to ensure it is always within the same thread? 我对线程技术还比较陌生,因此我不确定a)是否需要在此处进行此操作,或者b)可以采取一些措施来禁用这种可能性,或者通过更好地管理图对象来确保它总是在同一线程内?

Edit : This GraphController is first called from an .aspx.cs page with the following: GraphController.GraphController.Instance.GenerateGraph(data, details, "graph-type"); 编辑 :首先从.aspx.cs页面使用以下GraphController.GraphController.Instance.GenerateGraph(data, details, "graph-type");调用此GraphControllerGraphController.GraphController.Instance.GenerateGraph(data, details, "graph-type");

Second Edit : I have re-written the code to not have the ZedGraphControl as private static , but instead it is created within the GenerateGraph and then passed around where necessary. 第二次编辑 :我重新编写了代码,以免ZedGraphControl作为private static ,而是在GenerateGraph创建它,然后在必要时传递它。 Testing this up to 1,000 users in 60 seconds looks to have removed the cross-thread issues - does this sound likely? 在60秒内对多达1,000名用户进行测试似乎已消除了跨线程问题-听起来可能吗?

The issue here was the use of static variables. 这里的问题是static变量的使用。 As pointed out by Henk Holterman in the comments, static variables stay alive as long as the application process is alive, and is separate from any/all user requests. 正如Henk Holterman在评论中指出的那样,只要应用程序处于活动状态,静态变量就会保持活动状态,并且与任何/所有用户请求都分开。 So by having the ZedGraph object as a static variable it mean't that it was potentially still available to multiple requests without being cleared properly, running into memory and cross-threading issues. 因此,通过将ZedGraph对象作为static变量,并不意味着它可能仍可用于多个请求而没有被正确清除,从而导致内存和跨线程问题。

The solution is to declare the ZedGraph instance within the first GenerateGraph function and to then pass the same object to each other function that used it. 解决方案是在第一个GenerateGraph函数中声明ZedGraph实例,然后将同一对象传递给使用它的其他函数。 This ensures that it is the same object in the same thread that is accessed throughout the process. 这样可以确保在整个过程中访问的同一线程中的对象相同。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 在不是在其上创建线程的线程上访问控件 - Control accessed on a thread other than the thread it was created on 从不是在其上创建的线程的线程访问控件“ webBrowser1” - Control 'webBrowser1' accessed from a thread other than the thread it was created on 从不是在其上创建线程的线程访问控件“ dataGridView1” - Control 'dataGridView1' accessed from a thread other than the thread it was created on 从不是在其上创建线程的线程访问的控件“ x” - Control 'x' accessed from a thread other than the thread it was created on 从不是在C#中创建的线程的线程访问控件 - Control accessed from a thread other than the thread it was created on in C# 跨线程操作无效:控制“ chart1”从其他线程访问,而不是在其上创建的线程 - Cross-thread operation not valid: Control 'chart1' accessed from a thread other than the thread it was created on 跨线程操作无效:从不是在其上创建线程的线程访问控件“ statusStrip” - Cross-thread operation not valid: Control 'statusStrip' accessed from a thread other than the thread it was created on 跨线程操作无效:从创建它的线程以外的线程访问控件 - Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on Digital Personna SDK跨线程操作无效:从其他线程(不是在其上创建的线程)访问的控件 - Digital Personna SDK Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on 跨线程操作无效:控件从创建它的线程以外的线程访问 - Cross-thread operation not valid: Control accessed from a thread other than the thread it was created on
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM