Click here to Skip to main content
15,923,120 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I have a problem with threading. I want to have a processThread that I can reuse as many times as possible and also gives the ability of stopping an already running thread, dispose the running thread and start a new one in the same thread!

I have tried alot with just Thread and Task but can't get it work as I want.

The reason I want this is to simulate a RealTime calculation from a textbox field, there the thread will be called on KeyUp. And when the user continues to type in the same textbox the Thread that was called from the KeyUp should be restarted. This is connected to a special validation which includes some characters and therefore the process has to be restarted/aborted.

In this method I want to use Thread.Sleep(1500) just to make sure that the user has stopped typing.
The code is as following and this little code gives the error shown in the bottom:
if(processThread.IsAlive)
   {
       processThread.Abort();
   }


Code:
private Thread processThread;

private void incomeTBX1FP_KeyUp(object sender, KeyEventArgs e)
{
    bool processSucceed = false;
    if(processThread.IsAlive)
    {
        processThread.Abort();
    }

    Thread.Sleep(1500);
    processThread = new Thread((ThreadStart)delegate
        {
            ProcessValidationAndMemory(incomeTBX1FP.Text, income1LblFP.Text, 501, 1, out processSucceed);
            if (!processSucceed)
            {
                MessageBox.Show(incomeTBX1FP.Text + "innehåller ett felaktigt värde", "Ett fel har uppstått", MessageBoxButtons.OK, MessageBoxIcon.Error);
                incomeTBX1FP.Focus();
                incomeTBX1FP.SelectAll();
            }
        });
    processThread.Name = "InputThread";
    processThread.Start();

}


private void ProcessValidationAndMemory(string inputString, string inputLabel, short labelIndex, short incomeIndex, out bool processSucceed)
{
    double moneyValue;
    if (InputUtility.GetIncome(out moneyValue, inputString))
    {
        incomeArray[incomeIndex] = moneyValue;
        allLabels[labelIndex] = inputLabel;
        MessageBox.Show(incomeArray[incomeIndex].ToString() + " kr " + allLabels[labelIndex].ToString(), "TEST", MessageBoxButtons.OK);
        processSucceed = true;
    }
    else
    {
        processSucceed = false;
    }
}

Error Message:

System.NullReferenceException was unhandled
Message=Object reference not set to an instance of an object.
Source=My Economy Lite
StackTrace:
at My_Economy_Lite.MainWindows.incomeTBX1FP_KeyUp(Object sender, KeyEventArgs e) in C:\Users\Michael\documents\visual studio 2010\Projects\My Economy Lite\My Economy Lite\MainWindows.cs:line 39
at System.Windows.Forms.Control.OnKeyUp(KeyEventArgs e)
at System.Windows.Forms.Control.ProcessKeyEventArgs(Message& m)
at System.Windows.Forms.Control.ProcessKeyMessage(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.TextBoxBase.WndProc(Message& m)
at System.Windows.Forms.TextBox.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.Run(Form mainForm)
at My_Economy_Lite.Program.Main() in C:\Users\Michael\documents\visual studio 2010\Projects\My Economy Lite\My Economy Lite\Program.cs:line 18
at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args)
at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
InnerException:
Posted

In addition to Piccadilly's answer, there are several problems with your code:

1- Calling Abort is not recommanded. It is not a clean way to stop a thread. Besides, you need to handle the exception that will be raised from the running thread.
Instead I would recommand to use a BackgroundWorker, and use CancelAsync method (you will then need to check regularly the CancellationPending property from within the thread function).
One other important advantage about using a BackgroundWorkers is you can re-use it as many times as you want.

2- You are accessing UI objects from the thread (Text property, Focus method, and so on). Don't do that. Have a look to the InvokeRequired property, Invoke and BeginInvoke methods from MSDN to know more about that.
Instead, send arguments to your thread function.

But the main question is: do you really need a thread to do what you want to do? Can't you do all that in the event handler?
 
Share this answer
 
v3
Comments
[no name] 8-Mar-11 6:59am    
As I said, it is send to a special validation that will include three characters (optional of course, it is a kind of coding system). What I want is when you have stopped typing the ProcessValidationAndMemory is called. I don't know how to do that without Threading.

1- sounds good, is worth a try.

2- I'm not sure that I can do that though I will use same method against 40 textboxes...
johannesnestler 8-Mar-11 7:31am    
Very good answer Olivier Levrey!
@ mysoft: Use all the advices Olivier gave you. I can just repeat it. But the most important thing is, I don't think you need threads to do that. How expensive is a call to ProcessValidationAndMemory? Simple validation after input will maybe do. Have a look at your error handling too - You want 40 Threads to show MessageBoxes if something goes wrong? My advice: stop fiddling around with threading - rethink your design - and if you come to the conclusion threading is needed (long running validation, I can't believe it) - do it with BackgroundWorker and proper marshalling to the GUI thread (Invoke...) Good luck!
Olivier Levrey 8-Mar-11 7:34am    
You can pass a parameter to your thread function, this parameter can be the text from the text box for example. If you need more arguments, then you can pass an array or a class with all necessary things.
Sergey Alexandrovich Kryukov 8-Mar-11 11:39am    
Olivier, my 4 (not 5 because there is a problem of explanation of Abort).

You should have mentioned ThreadAbortException or better provide a sample. This this is not trivial. Also, I can list some important cases when Abort in unavoidable. The technology behind is very cunning and is based on exception seeding. This is not your old and dirty Terminate thread: through proper handling ThreadAbortException allowes to perform post-mortal clean up in the thread cleanly.

I would say not that it is not a clean way. I would prefer to say it requires expert understanding of threading to use it correctly (and when it is really unavoidable or beneficial). In particular, it should be calculated out what happens with inter-thread communication primitive and how other communicated threads shall behave in such orphaned situation.

I use it in many my applications, but those my applications are extremely exotic.

--SA
Olivier Levrey 8-Mar-11 11:54am    
I "grew up" with the old WIN32 API, so you are right assuming I make no difference between TerminateThread and Abort. My mind is still stucked with "don't terminate a thread or a process from an external source. Always use a quit request and let it quit by itself". So I've never investigated deeper in using Abort...
Try this :

C#
if(processThread!=null && processThread.IsAlive)
   {
       processThread.Abort();
   }


also stop thread before abort it
 
Share this answer
 
v2
Comments
Sergey Alexandrovich Kryukov 8-Mar-11 11:30am    
This is acceptable in certain cases and with certain.
I voted 3 not because this is unacceptable (in some situations this is unavoidable), but becuase you should have explained that correct handling of this situation should be based on handling ThreadAbortException inside thread. Without and good understanding how to handle it this step you suggestion is really bad.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900