I am using VS2010 .Net 4.0, so I cannot use the await calls. I have one thread downloading something, and I shouldn't continue before the status becomes "Done". So I am using a while loop blocking the thread. But somehow it becomes an infinite loop. Am I creating the thread properly?
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
// Loops here forever
while (status != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
}
You need to understand that thread.Join(); blocks in the calling thread until the thread being joined terminates. Once you understand that, you'll see that it is silly to do a while loop in the calling thread on the value of status, as if you've passed the join then the value of status will never change again unless you add code that does so.
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
//no point in looping here, if the thread finished, it has already assigned the
//value it is going to assign to the status variable
if (status == "Done")
{
//do what needs to be done
}
else
{
//uh oh, handle the failure here
}
To address the requirement that you cannot continue until status=="Done", you could instead place your while loop inside the child thread so that it keeps attempting the Download function until it returns "Done":
string status = string.Empty;
Thread thread = new System.Threading.Thread(() =>
{
while(status != "Done")
status = Download(downloadKit, patchTitle);
});
thread.Start();
thread.Join();
//do what needs to be done
Threading can result in some weird stuff sometimes, you need to sometimes tell the compiler that you are preforming something unsafe, you can do that by doing a var nstatus = Volatile.Read( ref status ) and then compare against that.
string nstatus = status;
// Loops here forever
while (nstatus != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
nstatus = Volatile.Read(ref status);
}
Other alternative is to use a Thread.MemoryBarrier() call, (which what I believe is being done in the Volatile call ), which prevents reordering of statements by compiler:
// Loops here forever
while (status != "Done")
{
//Thread.Sleep(25); // Tried this as well, same result
Thread.SpinWait(1);
Thread.MemoryBarrier();
}
A good resource to look at would be http://www.albahari.com/threading/part4.aspx , very in depth look at threading in .NET 4.0
Related
I want set a property where the value is in another thread
[DllExport]
public static bool Value()
{
bool val = false;
Thread thread = new Thread(async () => val = await getVal());
thread.IsBackground = true;
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
return val;
}
public async Task<bool> getVal()
{
bool value = false;
await Task.Factory.StartNew(() =>
{
string rs = new WebClient().DownloadString(url);
if (rs == "1")
value = true;
else
value = false;
});
return value;
}
It always returns false why I use that one is I cant use await in a static [DLLExport] method otherwise the form will freeze.
Edit: I cant use async in a DllExport method
Well starting the Thread really tells you nothing about when the code is being run.
After you call .Start() you tell the thread to run its code, but you have no real control of when the OS decides to actually let the code run.
Im also not sure how using locally defined variables inside the other thread-scope actually works, but I find it hard to think that you can set the value like you are trying to do.
Try googling Monitor.Wait(), Monitor.Pulse() which can be used to let one thread wait for another to finish (one calls Monitor.Wait() and the other calls Monitor.Pulse() when it wants the waiting thread to start executing).
I am using thread to multi tasks in winform solution, trying to abort the thread while its working but its not aborting, here is , is there any solution for this situation? need to make the thread abort/quit smoothly without any issues !
also is there any idea of how I can make the thread pause/resume?
Thanks in advance!
Thread CommentingThread;
CommentingThread = new Thread(async () =>
{
AddLog("Commenting process has been started!");
if (CommentBTN.InvokeRequired)
{
CommentBTN.Invoke((MethodInvoker)delegate () {
CommentBTN.Text = "Stop"; });
}
else
{
CommentBTN.Text = "Stop";
}
if (UrlListview.InvokeRequired)
{
if (UrlListview.InvokeRequired)
{
UrlListview.Invoke((MethodInvoker)async delegate ()
{
foreach (ListViewItem item in UrlListview.Items)
{
XtraMessageBox.Show(item.Text);
int timetodelay = RandomNumber.Next(int.Parse(CommentsMinDelayNumric.Value.ToString()), int.Parse(CommentsMaxDelayNumric.Value.ToString()));
await Task.Run(async () =>
{
await Task.Delay(timetodelay * 1000);
});
}
CommentBTN.Text = "Start";
AddLog("Commenting process has been finished sucessfully!");
});
}
}
else
{
foreach (ListViewItem item in UrlListview.Items)
{
XtraMessageBox.Show(item.Text);
int timetodelay = RandomNumber.Next(int.Parse(CommentsMinDelayNumric.Value.ToString()), int.Parse(CommentsMaxDelayNumric.Value.ToString()));
await Task.Run(async () =>
{
await Task.Delay(timetodelay * 1000 );
});
}
CommentBTN.Text = "Start";
AddLog("Commenting process has been finished sucessfully!");
}
#endregion
});
CommentingThread.Start();
if (CommentBTN.Text == "Stop")
{
CommentBTN.Text = "Start";
CommentingThread.Abort();
AddLog("Commenting process has been stopped!");
}
First of all, looking at your code, it seems that the Thread may stop immediately if UrlListview.Items does not contain any elements. You might be missing a while loop in this case.
Regarding the issue of stopping the thread:
Calling CommentingThread.Abort() will raise a ThreadAbortException which effectively crashes the thread (see the Microsoft Docs for more info for more info.
To shut a thread down gracefully you should either declare CancellationTokenSource or a boolean which can be set to true (or false, depending on your implementation), to notify the thread that it needs to be stopped. Here is an example:
var myThread_ctoks = new CancellationTokenSource();
Thread myThread = new Thread( async () =>
{
while (!myThread_ctoks.IsCancellationRequested) // simulate many long actions
{
await Task.Delay(TimeSpan.FromSeconds(2));
Console.WriteLine("Iteration finished!");
}
});
myThread.Start(); // start the thread
await Task.Delay(TimeSpan.FromMinutes(1)); // lets do some other work
myThread_ctoks.Cancel(); // and now shut down the thread
This thread checks every 2 seconds if a shutdown is required (because the simulated action takes that long). As soon as cancellation is requested (myThread_ctoks.IsCancellationRequested is set to true), the while condition will be false and thus the thread will end.
The benefit of doing it this way is that the thread will be shut down in a safe, defined way as it actually shuts down gracefully and doesn't crash.
Regarding how you could pause and resume a thread. You could also use a variable to control that, just by checking if the thread is allowed to do work or not. If it should pause then you would just wait for a second in a while loop.
There is also the possibility to use Thread.Suspend() and Thread.Resume(). There is however the possibility, according to Microsoft that you could lock up other threads under certain circumstances. Additionally, you do not know exactly what code is being executed when you interrupt it. Which may lead to further unexpected behaviour.
Thats why I am thinking its best to use a variable to control the thread behaviour.
I'm using threads to connect to multiple clients (PLCs) from my program. Program will send data and receive response from the PLC(s).. The problem im having is, when in debugging mode, (toggle breakpoint) one step at a time..the program work pretty much ok!, with the ID received confirming that it's coming from one of the thread.. but if I just debug without toggling any breakpoint, the response event will receive the same ID, although on different thread.. what could be wrong...
Debugging mode with breakpoint:
Debugging mode without breakpoint:
Below is my code
Start Request:
private void StartRequest()
{
foreach (ModbusTCP work in works)
{
work.Connect();
Thread.Sleep(1000);
if (work.Connected)
{
try
{
Thread thread = new Thread(new ThreadStart(() => work.StartReadHoldingRegister())) {
Name = ((ReadHoldingRegisterParam)work.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true
};
work.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
work.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
thread.Start();
threads.Add(thread);
}
catch (ThreadStateException ex)
{
MessageBox.Show(ex.Message);
}
}
else
work.Disconnect();
}
}
Response Event
private void modbus_OnResponseEvent(object sender, ModbusTCP.ResponseEventArgs e)
{
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
AddRow(RcvDataGrid, new PLCPacket() {
PLCId = e.id.ToString(),
PLCIp = "Test",
PLCTime = DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss tt"),
PLCData = ""
});
}));
}
}
}
Your variable work is shared among the threads. Once a thread is executed it takes whatever value your variable work has. That depends how quick each thread is processed. When you step through your code with a debugger you don't experience that.
If you capture the value before the anonymous method you should be fine:
try
{
// capture the current value of the loop variable
ModbusTCP localWork = work;
// so the anonymous method uses the reference in localWork
// instead of whatever value work has, which can be anywhere
// the future, worst case after your loop is finished, where
// work would hold the last value of the loop, and then
// start all threads with that value.
Thread thread = new Thread(
new ThreadStart(
() => localWork.StartReadHoldingRegister()))
{
Name = ((ReadHoldingRegisterParam) localWork.SetReadHoldingRegisterParam).id.ToString(),
IsBackground = true };
});
localWork.OnResponseEvent += new EventHandler<ModbusTCP.ResponseEventArgs>(modbus_OnResponseEvent);
localWork.OnExceptionEvent += new EventHandler<ModbusTCP.ExceptionEventArgs>(modbus_OnExceptionEvent);
A side comment:
lock (lockingObject)
{
if (e.data.Length > 0)
{
this.Dispatcher.BeginInvoke(new Action(() =>
{
This code is very unlikely to be correct. Here you are obtaining a lock in the original thread and then submitting a new action, async. The lock is scoped to the current method, and thus will be released as soon as the BeginInvoke call returns, not during the action itself. The only operations actually guarded by the lock is the e.data.Length check, which operates on a parameter (not shared) state and thus does not need protection.
It would make more sense to place the lock inside the action, but the action is always executed on the main thread and thus is unlikely to actually need protection (because is, basically, single threaded). Is difficult to guess exactly what you're trying to achieve w/o seeing the whole code, but that lock(lockingObject) is very unlikely to be necessary, or useful.
I have a method that occasionally hangs (in a dll I cannot modify but must use). If I run it again It will typically work fine. I was wondering if it would be possible to make a background thread that would wait for 20 minutes and then throw an exception in my program.
var triesLeft = 5;
while (triesLeft > 0) {
try {
var t = new Thread(() => { wait(20 minutes); throw new ApplicationHungException();})
t.Start();
Object o = MethodThatHangsForever10PercentOfTheTime();
} catch (ApplicationHungException e) {
triesLeft--;
}
}
t.Abort();
This does not work because the exception does not pass to the try catch block it's contained in. Is there a way I can get the thread to give it's exception to the try catch block?
One way to do this would be set off your faulty method in the separate thread, and wait for one of two things to happen; either:
The thread completes, or
A predetermined amount of time (eg 20 mins) elapses
Once either of these things happens, we can take appropriate action.
The code would look something like this:
static void DoProcessing() {
var triesLeft = 5;
Object o = null;
while (triesLeft > 0) {
var t = new Thread(() => { o = MethodThatHangsForever10%OfTheTime(); }).Start();
if (t.Join(new TimeSpan(0, 20, 0))) {
// The thread completed
break;
} else {
// We're out of time.
t.Abort(); // Important: See comments below about this
triesLeft--;
}
}
}
It turns out that aborting threads is a risky and fragile operation, as pointed out by Reed Copsey in the comments below. Your alternatives are to allow the hung thread to live out the rest of its life (however long that may be), or to quarantine the Heisenbuggy method call to a separate process.
This opens up another can of worms however, since you would have to deal with interprocess communication, data serialization and synchronisation. This may or may not be worth it, which is a judgement call I leave to you.
You can do your work in a separate thread, and wait 20 minutes for it to complete:
var triesLeft = 5;
while (triesLeft > 0)
{
var mre = new ManualResetEvent(false);
ThreadPool.QueueUserWorkItem(_ => {
MethodThatHangsForever10PercentOfTheTime();
mre.Set();
});
if (mre.WaitOne(TimeSpan.FromMinutes(20)))
{
break; // Success!
}
triesLeft--;
}
}
I'm not to sure about something about EventWaitHandle.Set.
When called from within current thread and there is another thread waiting for the event, do the current thread get to sleep so that other thread gets to run (ASAP)?
I'm asking because in some of my code I have to add some object to a "threads shared" queue and that operation has really to go as quick as possible. But in the other thread where that queue is being used, speed is "not required".
So I'm proceeding like this:
// Speed "not required"
mailThread = new Task(() =>
{
for (; ; )
{
MailMessage mail;
pushMailLockMREvt.WaitOne();
{
if (mails.Count == 0)
{
mail = null;
}
else
{
mail = mails.Dequeue();
}
}
pushMailLockMREvt.Set(); // Does this put current on sleep on lower it's priority??
if (mail != null)
{
try
{
MailClient.Send(mail);
}
catch (Exception exe)
{
}
}
else
{
mailSem.WaitOne();
}
}
});
[...]
// Speed required
var task = new Task(() =>
{
pushMailLockMREvt.WaitOne(); // ASAP please...
{
mails.Enqueue(mailMessage);
if (mails.Count == 1)
{
mailSem.Set();
}
}
pushMailLockMREvt.Set();
});
No, the current thread will not sleep just because it signals the wait handle. But it may relinquish the rest of its timeslice (that's pretty subtle and low-level and isn't something you should rely on). You should not need to take any special action.
It is probably the case that the thread that has just finished waiting will get a brief boost in thread priority.
See this documentation for the Windows API function SetThreadPriorityBoost() from which I quote:
When a thread is running in one of the dynamic priority classes, the system temporarily boosts the thread's priority when it is taken out of a wait state.
Also see this documentation.
So the thread that just woke up from the wait should (normally) get a small boost. I'm not totally sure that this also applies to managed threads, but I seem to remember reading somewhere that it does. I can't find the source of that, though.