开发者

c# how to properly stop a thread and start it back?

开发者 https://www.devze.com 2023-02-28 12:36 出处:网络
I have a method which does some work and calls a method after it\'s done. In this newly called method, I stopped the thread.

I have a method which does some work and calls a method after it's done. In this newly called method, I stopped the thread.

however if I stop the thread, all the following line will not be read. Is there any proper way to stop the thread and start it back?

Here is my code snippet:

public partial class Form1 : Form
{
    string strProvider;
    MySqlConnection sqlConn;
    MySqlCommand command;
    MySqlDataReader Reader;

    Thread workerThread;

    public Form1()
    {
        InitializeComponent();
        initializedb();
        workerThread = new Thread(shows);
        workerThread.Start();
        workerThread.IsBackground = true;

    public void shows()
    {
        string k;

        command.CommandText = "SELECT * FROM imageframe1";
        sqlConn.Open();
        Reader = command.ExecuteReader();

        while (Reader.Read())
        {
            k = (string)(Reader.GetValue(1));
            pictureBox1.Image = Image.FromFile(k);
            Thread.Sleep(3000);
        }

        sqlConn.Close();

        stopthread();
    }

    public void stopthread()
    {
        workerThread.Abort();
        //*************everything after this line wont run********
        MessageBox.Show("end");
        //Thread.Sleep(3000);
        //workerThread.Start();
    }
开发者_开发知识库

what im doing here is that im doing a slideshow of pictures.so i want to stop the thread and start it back,check db for new images and re run the whole thing instead of looping inside of it will use a lot of memory resources.but problem is when i stop it, i cant run anything after that.

could anyone please shed some light for a beginner here??with examples would be really good for me to understand.


This is not the way to pause a program. If you would like the user to be able to temporarily pause reading from your reader, a better way is to handle this is by setting some flag that the while loop can check upon each iteration. Threads should never be directly manipulated by calling Thread.Abort. So instead of trying to stop the thread, your "stopthread" method should actually look more like this:

private object lockObject = new object();
private bool isPaused;

public void stopthread()
{
    lock (lockObject) 
    {
        isPaused = true;
    }
    //*************everything after this line wont run********
    MessageBox.Show("end");
}

Now, in order to actually respect this pause action, you must modify the reading to check this flag. One approach would be to check if it's paused in each iteration of reading from the reader and if so, wait until it becomes unpaused:

public void shows()
{
    ...

    while (Reader.Read())
    {
        while (true) 
        {
            lock (lockObject) 
            {
                if (!isPaused)
                    break;
            }
            Thread.Sleep(1000);
        }

        k = (string)(Reader.GetValue(1));
        pictureBox1.Image = Image.FromFile(k);
        Thread.Sleep(3000);
    }

    ...
}

Of couse, you'd also want a "startThread" method as well:

public void startThread() 
{
    lock (lockObject) 
    {
        isPaused = false;
    }
    MessageBox.Show("start");
}

This approach has the downside that it leaves the SQL connection open and ties up a thread while paused. Another approach would be to remember how many rows you've processed and simply restart the thread when you unpause, starting from where you left off. You'd want to stop the thread in a similar way -- checking the flag if it's paused and closing the connection and cleaning up when stopping. Then when unpausing you'd have to start the process from the beginning with a new thread, somehow managing to skip the ones you've already processed -- possibly involving an adjustment of the SQL.

A final thing to consider is to use thread pools instead of creating threads manually, though for a WinForms app, the cost is probably inconsequential.


Here is a great series about C# threading. Really, I mean it. You may want to take a look a it since finding solutions when dealing with thread is not only about finding a solution but most importantly really understand what's happening besides ;)

http://www.albahari.com/threading/

My grand'ma always used to say "Don't mess with Threads"... And she was right...


I would recommend looking at the ManualResetEvent class. You can have your thread wait for it to be signaled from the UI thread and then continue. The ManualResetEvent class can have two states: signaled or nonsignaled. Threads can call WaitOne() which will not return until the state becomes signaled (or return immediately if the state is already signaled). You set it to signaled by calling Set() and reset it to nonsignalled by calling Reset():

public partial class Form1 : Form
{
    string strProvider;
    MySqlConnection sqlConn;
    MySqlCommand command;
    MySqlDataReader Reader;

    Thread workerThread;
    ManualResetEvent manualReset;

    public Form1()
    {
        InitializeComponent();
        initializedb();
        workerThread = new Thread(shows);
        workerThread.Start();
        workerThread.IsBackground = true;
        manualReset = new ManualResetEvent(true); // true for allow running
    }

    public void shows()
    {
        string k;

        command.CommandText = "SELECT * FROM imageframe1";
        sqlConn.Open();
        Reader = command.ExecuteReader();

        while (Reader.Read())
        {
            k = (string)(Reader.GetValue(1));
            pictureBox1.Image = Image.FromFile(k);
            Thread.Sleep(3000);
            manualReset.WaitOne(); // wait if reset
        }

        sqlConn.Close();

        stopthread();
    }

    public void pauseThread()
    {
        manualReset.ReSet();
    }

    public void continueThread()
    {
        manualReset.Set();
    }
}

However, why not simply put a timer on your form and set the Interval to 3000 ms and load the image in the UI thread? It looks like you just get the file names from the database. If there aren't too many you should pre-load them into a List and keep track of your position instead of maintaining an open connection and reader. 10,000 strings of 100 chars each would only take up about 200k of memory.

0

精彩评论

暂无评论...
验证码 换一张
取 消