0

Currently, I am using a thread to autofill a zedgraph chart. The problem is that it is very slow and that is not good for the production.

Knowing that:
1. There is a Thread running background to get fresh data from remote server and store them in a local text file.
2. There is another Thread accesses and reads data from the local file and refresh the zedgraph chart.

Personnaly I think this makes the application running very slowly.
Timer component may be better to handle this kind of stuff.
Does anyone has experience in ZedGraph Live Data?
Or any advice would be welcomed.


EDIT: UPDATE UI
Also I would like to know how to update the UI within a Thread so that the user does not have to close and open the form to view the chart.
Thanks

John Saunders
  • 160,644
  • 26
  • 247
  • 397
DeathCoder
  • 145
  • 1
  • 4
  • 19
  • 1
    I don't know how much data you put into that file but 99.9% of the time it's better to keep the data in memory so you can access it quicker. (in other words save it in a variable and read it from the graph's thread) – Manuel Jan 09 '13 at 12:37
  • 1
    Why would a Timer be better? I do not get the point. – usr Jan 09 '13 at 12:46
  • have you thought about a backgorundworker without file access? – Offler Jan 09 '13 at 13:10
  • Like @dragon112 says, do you really need the local file for something else? If not, use inter-thread comms, (producer-consumer queue, perhaps), to transfer the data directly - that's a big advantage of threads - all share the same app memory. – Martin James Jan 09 '13 at 13:15
  • hi @dragon112, do you have any link explaining the use of this? getting data with a thread, save in memory and access them to update the UI. – DeathCoder Jan 09 '13 at 13:56
  • @MartinJames what about inter-thread comms ? knowing that I have 12 small Forms inside a splitContainer and all the Forms have to be loaded at startup. What can I adopt in this case ? – DeathCoder Jan 09 '13 at 14:01
  • Hello, no-one can suggest an issue? – DeathCoder Jan 10 '13 at 12:16

1 Answers1

1

The way I would go about this is as follows:

You make a class that holds the data (this can also be the same class you already have) for the example I will call it InformationHolder.

class InformationHolder {
    private static InformationHolder singleton = null;
    public List<float> graphData; //Can be any kind of variable (List<GraphInfo>, GraphInfo[]), whatever you like best.

    public static InformationHolder Instance() {
        if (singleton == null) {
            singleton = new InformationHolder();
        }

        return singleton;
    }
}

Now you need a class that will get your information in the background, parses it and inserts it into the above class.

Example with Thread.Sleep():

class InformationGartherer {
    private Thread garthererThread;

    public InformationGartherer() {
        garthererThread = new Thread(new ThreadStart(GartherData));
    }

    private void GartherData() {
        while (true) {
            List<float> gartheredInfo = new List<float>();

            //Do your garthering and parsing here (and put it in the gartheredInfo variable)

            InformationHolder.Instance().graphData = gartheredInfo;

            graphForm.Invoke(new MethodInvoker( //you need to have a reference to the form
                   delegate {
                       graphForm.Invalidate(); //or another method that redraws the graph
                   }));

            Thread.Sleep(100); //Time in ms
        }
    }
}

Example with Timer:

class InformationGartherer {
    private Thread garthererThread;
    private Timer gartherTimer;

    public InformationGartherer() {
        //calling the GartherData method manually to get the first info asap.
        garthererThread = new Thread(new ThreadStart(GartherData));

        gartherTimer = new Timer(100); // time in ms
        gartherTimer.Elapsed += new ElapsedEventHandler(TimerCallback);
        gartherTimer.Start();
    }

    private void TimerCallback(object source, ElapsedEventArgs e) {
        gartherThread = new Thread(new ThreadStart(GartherData));
    }

    private void GartherData() {
        List<float> gartheredInfo = new List<float>();

        //Do your garthering and parsing here (and put it in the gartheredInfo variable)

        InformationHolder.Instance().graphData = gartheredInfo;

        graphForm.Invoke(new MethodInvoker( //you need to have a reference to the form
                delegate {
                    graphForm.Invalidate(); //or another method that redraws the graph
                }));
    }
}

To get the reference to the form you could do the same trick as I used with the InformationHolder: using a singleton. When you want to use the information just get it from the InformationHolder like so:

InformationHolder.Instance().graphData;

As I said this is how I personally would solve this. There might be a better solution I'm not aware of. If you have any questions you can post them below.

Manuel
  • 10,153
  • 5
  • 41
  • 60
  • Thanks @dragon112 for your reply. I have question,,the class InformationGartherer has to be instanciated somewhere in the code and where? in the Form or where ? Can I call this class InformationHolder directly in the Form? – DeathCoder Jan 10 '13 at 21:44
  • Really, I don't know how to use these functions. Can you modify in a way to get fresh data from a remote server? Something like inside the Thread: - Connect to remote server; - Get Time and OCHL data, store them to a List variable; - Send these variables to zedGraph to draw chart. – DeathCoder Jan 11 '13 at 03:39
  • Basically you should use something like `HttpWebRequest` to `POST` to a web service and possebly receive a response. If you need to use a `GET` request you can use `WebRequest`. There are tons of examples out there. If you can't figure it out I'll try to help you out. – Manuel Jan 11 '13 at 09:13
  • If you call the `InformationHolder` it will initiate itself (in the `Shared()` method). The `InformationGartherer` however doesn't have such a method and needs to be created by a normal `new InformationGartherer()` call. – Manuel Jan 11 '13 at 10:34