0

I've created a thread (or I'm trying to) which will autosave every so many minutes. Whenever I click the button to start the thread, the program doesn't autosave as instructed. So I'm reaching out for help. Here's the code:

private Thread saver;
...
saver.SetApartmentState(System.Threading.ApartmentState.STA);
saver = new Thread(new ThreadStart(SaveRegularly));
saver.Start();

Here's my SaveRegularly method:

private bool stopAndDie = false;
private void SaveRegularly()
 {
   //DateTime saveDueAt = DateTime.Now.AddMinutes(0.25);
   //do
     //{
        //Thread.Sleep(1000);
        //if (DateTime.Now >= saveDueAt)
     //{
        if (SaveDoc.FileName != "")  //ADDED THIS TODAY (24/09)
          {
            CreateWordDocument(FilePath, SaveDoc.FileName, pathImage);
            MessageBox.Show("Updated");
            return;
          }
        else
          {
             if (SaveDoc.ShowDialog() == DialogResult.OK)
              {
                CreateWordDocument(FilePath, SaveDoc.FileName, pathImage);
                MessageBox.Show("New Save");
                return;
              }
           }
            timer1.Start();
     }

This is for the FormClosing Event, so the thread stops.

        stopAndDie = true;
        saver.Join(2000);
        timer1.Stop();

When I run the program and I click the save button, I receive an error at the SaveFileDialog line (if (SaveDoc.ShowDialog() == DialogResult.OK)).Here is the error I receive. enter image description here

Kayla
  • 165
  • 2
  • 4
  • 13

1 Answers1

1

Set the thread to STA mode.

saver.SetApartmentState(System.Threading.ApartmentState.STA);

But why aren't you using timers if you want to schedule something periodically? Something like this:

System.Timers.Timer timer = new System.Timers.Timer(5 * 60 * 1000);
timer.Elapsed += (s, e) =>
    {
       //Invoke your show dialog on the UI thread here
    };
timer.Start();

And when you want it to stop just call timer.Stop();

Marko Devcic
  • 1,069
  • 2
  • 13
  • 16
  • I just updated the code with your recommendations. I used a timer (timer1) and I set the value in the properties window. Does it look okay? Thanks for your help! – Kayla Sep 27 '15 at 10:48
  • When I run the program now, I get an error at the line `saver.SetApartmentState(System.Threading.ApartmentState.STA);`. The error says, "An unhandled exception of type 'System.NullReferenceException' occurred in FindAndReplace.exe Additional information: Object reference not set to an instance of an object." – Kayla Sep 27 '15 at 10:51
  • Move the SetApartmentState call one line down, or you'll get null reference exception. Also, I meant if you are going to use timers then you don't need all that threading ... So, either just put the SetApartmentCall into your original code ... or replace everything with timers – Marko Devcic Sep 27 '15 at 10:52
  • Deva, I want your opinion on something. I'm creating a document that takes about 5-10 seconds to save. I want to make the program autosave (once the save button is clicked, so a SFD doesn't appear out of thin air while the user is typing). So I've decided to go with the thread idea so it will save in the background and the user can still work, uninterrupted. When the save button is clicked, the timer will start and continue until they exit. Kind of like MS Word. Do you think the thread implementation is the best approach? – Kayla Sep 27 '15 at 11:11
  • Well since timers fire on a thread pool where all threads are MTA, that would mean that you would have to first invoke the save dialog on a UI thread and then invoke the actual save to file code on an another thread. Now if you feel that you know how to do it, then sure write it that way. But it seems to me that you would have trouble with it. So I would just leave your original code and add the SetApartmentCall – Marko Devcic Sep 27 '15 at 11:32
  • Thanks for your help. Threads and the terminology associated with them are all new to me, so please forgive me when I ask, what is MTA? Also, do you have any suggestions on where to place the SetApartmentCall within the code? In a separate question, in my save command, I have a method called "CreateWordDocument". Do I need to do anything with that method? Eg, add a SetApartmentCall, or anything else at that location? I can supply the code for the method, if it helps. Thanks again for your patience. I'm literally a rookie at threads and related approaches. – Kayla Sep 27 '15 at 13:37
  • STA and MTA, read this ... http://stackoverflow.com/questions/127188/could-you-explain-sta-and-mta. Call the SetApartmentState immediately after constructor call. Once it is set, you don't have to set it anymore. STA is only important for ShowDialog call. – Marko Devcic Sep 27 '15 at 14:13