Stop a thread if it takes too long - c#

I am new in Windows Phone development and I am trying to create a windows phone app using C#
Thread t = new Thread(doaheavywork);
t.Start();
if (!t.Join(1000)) // give the operation 1s to complete
{
t.Abort();
}
I cannot alter the doaheavywork function.
I just need the result to be omputed within 1 or 2 seconds, since sometimes it may run for very long time.
I have read using abort is the wrong way.
I am using the above in a PhotoChooserTask complete function. First run executes fine. That is, when I click the button to select a photo, the doaheavywork function doesn't exceed 1 sec. But if I try for the second time, the PhotoChooserTask just throws an exception and stops.
Is it because I aborted the process in 1st run? Or anything else? Is there any other way to do it?

.Abort() causes the thread to be destroyed completely. If you are generating a new thread each time like in your example, then it will work. However if you are using the same t object, then you need to create a new thread object, you can't run .Start() on an aborted thread.
However the fact you are aborting a thread is a concern. What happens with the application when it does take more than 2 seconds. Should you be showing the user, please wait, its taking longer than expected. Doing that in the if block is where to do it. .Join() won't stop the thread even if it doesn't manage to join.
Edit
You have 2 options you might want to consider in rewriting this section:
BackgroundWorker - http://msdn.microsoft.com/en-us/library/system.threading.tasks.task.aspx
Thread Task - http://msdn.microsoft.com/en-us/library/windowsphone/develop/cc221403(v=vs.105).aspx
Tasks seem to be the appropriate solution in your scenario.

One approach maybe be to consider using a Task and having a CancellationToken passed in to it from a CancellationTokenSource instantiated against a specific timespan - 2 seconds. That way when the the time specified has elapsed, the CancellationToken, passed to the Task, will be signaled and then appropriate action can be taken.

Related

C# finding managed thread

I'm using the System.Threading.Thread object to create a background-working method. The method loads data which can also be used by the user in the current time (must be read from the same source). That's why I'd like to find the created Thread and pause it for the time of current data-loading.
Here comes the problem... How to find the Thread?
I've already read about System.Diagnostics.Process attempt, but it contains data only about the OS-Threads.
Also I need to say that the method starting the Thread is static and it's possible but really unwanted to create an object to track the thread. I'm just creating new object and starting it...
(new Thread(new ThreadStart(...))).Start();
I've looked through many topic but I found no following question:
IF IT'S IMPOSSIBLE, THAN FROM WHERE THE VISUAL STUDIO -> THREAD WINDOW TAKES INFORMATION!?
Thanks in advance for any help :)
If pausing the "reading" thread is truly required, you can have it wait for a signal using the EventWaitHandle class, set as Manual or Automatic reset depending on your use case, starting unset. The background thread, when it has finished writing to whatever the shared variable location is, can set the signal on the wait handle to release the "reading" thread that was stuck waiting.
If your "reading" thread only needs to pause sometimes, you can use the same wait handle approach, except have it start as "set" in Manual Reset mode while your "reading" thread checks it whenever appropriate. The "reading" thread will skip over waiting for the signal (because it's already set)!
Once your "writing" thread needs to make a change, it would reset the wait handle, causing your "reading" thread to pause when it checks for the signal, update the data, then "set" the signal again to release the paused "reading" thread.
Use Task for background work and you can utilize Continue method to process the data on completion of task.
var task = Task.Run(() => "Test");
task.ContinueWith((str) => "Process data");
Or utilize Name property of Thread class to assign the name.

await Task.Delay takes longer than expected

I wrote a multithreaded app which uses async/await extensively. It is supposed to download some stuff at a scheduled time. To achieve that, it uses 'await Task.Delay'. Sometimes it sends thousands requests every minute.
It works as expected, but sometimes my program needs to log something big. When it does, it serializes many objects and saves them to a file. During that time, I noticed that my scheduled tasks are executed too late. I've put all the logging to a separate thread with the lowest priority and the problem doesn't occur that often anymore, but it still happens. The things is, I want to know when it happens and in order to know that I have to use something like that:
var delayTestDate = DateTime.Now;
await Task.Delay(5000);
if((DateTime.Now - delayTestDate).TotalMilliseconds > 6000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
Moreover, I have found that 'Task.Run', which I also use, can also cause delays. To monitor that, I have to use even more ugly code:
var delayTestDate = DateTime.Now;
await Task.Run(() =>
{
if((DateTime.Now - delayTestDate).TotalMilliseconds > 1000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
//do some stuff
delayTestDate = DateTime.Now;
});
if((DateTime.Now - delayTestDate).TotalMilliseconds > 1000/*delays up to 1 second are tolerated*/) Console.WriteLine("The task has been delayed!");
I have to use it before and after every await and Task.Run and inside every async function, which is ugly and inconvenient. I can't put it into a separate function, since it would have to be async and I would have to await it anyway. Does anybody have an idea of a more elegant solution?
EDIT:
Some information I provided in the comments:
As #YuvalItzchakov noticed, the problem may be caused by Thread Pool starvation. That's why I used System.Threading.Thread to take care of the logging outside of the Thread Pool, but as I said, the problem still sometimes occur.
I have a processor with four cores and by subtracting results of ThreadPool.GetAvailableThreads from ThreadPool.GetMaxThreads I get 0 busy worker threads and 1-2 busy completion port threads. Process.GetCurrentProcess().Threads.Count usually returns about 30. It's a Windows Forms app and although it only has a tray icon with a menu, it starts with 11 threads. When it gets to sending thousands requests per minute, it quickly gets up to 30.
As #Noseratio suggested, I tried to play with ThreadPool.SetMinThreads and ThreadPool.SetMaxThreads, but it didn't even change the numbers of busy threads mentioned above.
When you execute Task.Run it uses Thread Pool threads to execute those tasks. When you have long running tasks, you are causing starvation to the Thread Pool, since its resources are currently occupied with long running tasks.
2 Suggestions:
When running long running tasks, make sure to use Task.Factory.Startnew with TaskCreationOptions.LongRunning, which will trigger a new thread creation. You must be cautious here as well, as spinning too many new threads will cause excessive context switches which will cause your app to slow down
Use true async where you have to do IO Bound work, use apis that support the TAP such as HttpClient and Stream, which wont cause a new thread to execute blocking work.
There are overheads in async/await, as well as the tasks themselves being executed at a lower priority. If you need something to happen reliably at an accurate interval, async/await / TPL is not the interface to use.
Try creating an independent background thread that loops until it is scheduled to do work. This way you can control the priority and timing directly without going through TPL / async.
Thread backgroundThread = new Thread(BackgroundWork);
DateTime nextInterval = DateTime.Now;
public void BackgroundWork()
{
if(DateTime.Now > nextInterval){
DoWork();
nextInterval = nextInterval.Add(new TimeSpan(0,0,0,10)); // 10 seconds
}
Thread.Sleep(100);
}
Adjust the Sleep(..) and interval values as needed.
I think you're experiencing the situation described by Joe Duffy in his "CLR thread pool injection, stuttering problems" blog post:
One silly thing our thread pool currently does has to do with how it
creates new threads. Namely, it severely throttles creation of new
threads once you surpass the “minimum” number of threads, which, by
default, is the number of CPUs on the machine. We limit ourselves to
at most one new thread per 500ms once we reach or surpass this number.
One solution might be to explicitly increase the minimum number of thread pool threads before making any use of TPL, e.g.:
ThreadPool.SetMaxThreads(workerThreads: 200, completionPortThreads: 200);
ThreadPool.SetMinThreads(workerThreads: 100, completionPortThreads: 100);
Try playing with these numbers and see if the problem goes away.

Proper way to delay code execution in a background worker

Ok so I've been reading up on Thread.Sleep, Task.Delay, AutoResetEvent ...etc
I see lots of arguments over which to use as it depends on the task being performed.
I currently use Thread.Sleep in everything and think I need to start avoiding it and use a better practice.
It's a client side app that contains a BackgroundWorker. The worker runs once every 30 minutes to check for updated data from a web service.
It then updates 3 int vars located in MainWindow. These don't do anything with the UI. They are just used in checks for other workers that are running.
Is one way to delay better than another?
If a user exit's the application and I'm calling Application.Current.Shutdown(), will it continue to run until Thread.Sleep has finished or will it exit even if a thread is sleeping?
use a combination of Task, await and CancellationTokenSource to be able to run in background, wait without wasting a thread, and cancel.
Something like:
var cancel = new CancellationTokenSource();
App.OnShutdown += (s,e) => cancel.Cancel();
await Task.Delay(1000,cancel.Token);

EventWaitHandle sometimes! skip thread

I am using VS 2012, .Net 4.5.
Execute this code (just upgrade some sample from article about threading):
using System.Threading;
class BasicWaitHandle
{
static EventWaitHandle wh = new AutoResetEvent(false);
static void Main()
{
new Thread(Waiter).Start();
new Thread(Waiter).Start();
Thread.Sleep(1000); // Подождать некоторое время...
wh.Set(); // OK – можно разбудить
wh.Set();
Console.ReadLine();
}
static void Waiter()
{
Console.WriteLine("Avait..."+Thread.CurrentThread.ManagedThreadId);
wh.WaitOne(); // Ожидать сигнала
Console.WriteLine("Got a signal"+Thread.CurrentThread.ManagedThreadId);
}
}
I Debug it few times, but usually (not always) get wrong result. At first (once or more times) it correct:
Avait...10
Avait...11
Got a signal 11
Got a signal 10
But then it just start skipping one thread (somethimes first? somethimes second):
Avait...10
Avait...11
Got a signal 11 (or 10)
And program just does not react. In a few minutes it gives some correct results, but then go wrong again...
Moreover, when i debugging it step-by-step it always acting correctly.
So, maybe I should choose another approach? But this looks like what I expected, even if threads got signals in random order...
I am pretty unsure you can use same AutoResetEvent for multiple awaters, because Set is not waiting for first thread to complete its Wait:
There is no guarantee that every call to the Set method will release a thread from an EventWaitHandle whose reset mode is EventResetMode.AutoReset. If two calls are too close together, so that the second call occurs before a thread has been released, only one thread is released. It is as if the second call did not happen. Also, if Set is called when there are no threads waiting and the EventWaitHandle is already signaled, the call has no effect.
I'd go with ManualResetEvent and synchronization during setting signal (to ensure, what waiting thread receive signal) or (better) use dedicated event for each waiting function (every thread would start with its own event to wait for, you will need kind of manager for those thread to create waiting event and to have Set method what will signal all these events).
p.s.: can repeat said above in russian btw ^^
Both threads start and run until they block on the WaitHandle. When the WaitHandle is set, one thread will wake up and the event will reset.
You can't guarantee which thread will wake up, so the order isn't ensured. When running correctly, either 10 or 11 will wake up, followed by the other, every time.
In the case where your application hangs, the problem is the execution order. The main thread is executing both calls to Event.Set() prior to the first thread waking up. The AutoResetEvent is not a counter, it is either set or unset, so the second call to Set() is lost.
If you Sleep() between calls to Set(), you will yield to the other threads and give one of them time to wake up and reset the event.
In the case where it works correctly, you are just getting lucky and the waiting threads are getting a chance to run between calls to Set(). This is referred to as a race condition.

c# sleeping thread problem

what is the problem in the code part below? Any ideas? I m sending command to my device through serial port. After each command the device will work for this command and then the other command comes for it and continues like this.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
I figured out if i erase second sleep and function3 from the code like below, it does both two function but if i want to continue like this way it does not do the third one.
in Button Click event
{
function1();
Thread.Sleep(5000);
function2();
}
works...
Thank you
You're blocking the UI thread. Don't do that. It means your UI can't update itself. Instead, set a System.Windows.Forms.Timer to fire in 5 seconds with the next function to call. Alternatively, do all of this in a different thread entirely (possibly using Sleep, possibly using another kind of timer to fire on a thread-pool thread) and use Control.Invoke/BeginInvoke to marshall back to the UI thread when you need to update the UI itself.
EDIT: Given your "answer", it seems that blocking the UI thread was only one of the problems - and getting the device to respond properly at all is a bigger problem. You shouldn't just rely on sleeping for a certain amount of time. You should detect when the device has completed the previous command. It's possible that it doesn't give any feedback, but that would be horrifically poor design. If at all possible, investigate how to read feedback from the device as to when it's finished (e.g. reading from the serial port!) and only start the next command when the previous one has finished. Depending on how you receive the feedback, you could use a blocking call on a non-UI thread, or use an asynchronous model to trigger things.
The BackgroundWorker might be a solution to solve the blocking of the UI.
Get rid of the Sleeps If the functions are creating their own threads, give them callback methods that trigger the next function after the first has finished.
As the code is presented there it is nothing wrong with it. It will:
Execute function 1
Sleep 5 seconds
Execute function 2
Sleep 5 seconds
Execute function 3
However since this is on a GUI event it will freeze the application while doing so. Consider spinning off the execution into a thread instead.
In .Net 4.0:
Task.Factory.StartNew(() => sendData());
In all .Net versions:
System.Threading.Thread myThread = new System.Threading.Thread(sendData);
myThread.IsBackground = true;
myThread.Start();
And then you have your sendData method:
private void sendData()
{
function1();
Thread.Sleep(5000);
function2();
Thread.Sleep(5000);
function3();
}
If you really need to do stuff in the GUI thread you can make it more responsive by regularly calling Application.DoEvents();, but this is not a good way of solving it.
Also remember that you can't access the GUI from other threads. See http://kristofverbiest.blogspot.com/2007/02/simple-pattern-to-invoke-gui-from.html for sample code on how to invoke the GUI thread from other threads.
Thank you guys. I solve it. The problem is i did not make thread sleep enough. 5000 ms do not enough for the second command.

Categories

Resources