Detect Boolean value changes inside Thread - c#

I have a c++ dll function that i want to run inside the C# thread.
Some times I need to cancel that thread, and here is the issue :
Thread.Abort() is evil from the multitude of articles I've read on
the topic
The only way to do that was to use a bool and check it's value periodically.
My problem that even i set this value to true it didn't change and still equal to false in c++ code. However when I show a MessageBox that value changed and it works fine.
Any ideas why that value changed only when the MessageBox showed and please tell me how to fix that issue.
C#
public void AbortMesh()
{
if (currMeshStruct.Value.MeshThread != null && currMeshStruct.Value.MeshThread.IsAlive)
{
//here is my c++ Object and cancel mesh used to set bool to true;
MeshCreator.CancelMesh();
}
}
C++
STDMETHODIMP MeshCreator::CancelMesh(void)
{
this->m_StopMesh = TRUE;
return S_OK;
}
when I test the boolean value
if (m_StopMesh)
return S_FALSE;
The value here is always false even i call AbortMesh()
if (m_StopMesh)
return S_FALSE;
MessageBox(NULL,aMessage,L"Test",NULL);
if (m_StopMesh) // here the value is changed to true
return S_FALSE;

The non-deterministic thread abortion (like with Thread.Abort) is a really bad practice. The problem is that it is the only practice that allows you to stop your job when job does not know that it could be stopped.
There is no library or framework in .NET I know of that allows to write threaded code that could allow you to run an arbitrary task and abort it at any time without dire consequences.
So, you was completely write when you decided to use manual abort using some synchronization technique.
Solutions:
1) The simplest one is using of a volatile Boolean variable as it was already suggested:
C#
public void AbortMesh()
{
if (currMeshStruct.Value.MeshThread != null && currMeshStruct.Value.MeshThread.IsAlive)
{
MeshCreator.CancelMesh();
}
}
C++/CLI
public ref class MeshCreator
{
private:
volatile System::Boolean m_StopMesh;
...
}
STDMETHODIMP MeshCreator::CancelMesh(void)
{
this->m_StopMesh = TRUE;
return S_OK;
}
void MeshCreator::ProcessMesh(void)
{
Int32 processedParts = 0;
while(processedParts != totalPartsToProcess)
{
ContinueProcessing(processedParts);
processedParts++;
if (this->m_StopMesh)
{
this->MakeCleanup();
MessageBox(NULL,aMessage,L"Test",NULL);
}
}
}
Such code should not require any synchronization if you do not make any assumptions on completion of thread after the CancelMesh call - it is not instantaneous and may take variable amount of time to happen.
I don't know why the use of the volatile didn't help you, but there are few moments you could check:
Are you sure that the MeshCreator.CancelMesh(); method call actually happen?
Are you sure that m_StopMesh is properly initialized before the actual processing begins?
Are you sure that you check the variable inside the ProcessMesh often enough to have decent response time from your worker and not expecting something instantaneous?
2)Also if you use .NET 4 or higher you could also try to use the CancellationToken-CancellationTokenSource model. It was initially designed to work with Tasks model but works well with standard threads. It won't really simplify your code but taking into an account the async nature of your processing code will possibly simplify future integration with TPL
CancellationTokenSource cancTokenSource = new CancellationTokenSource();
CancellationToken cancToken = cancTokenSource.Token;
Thread thread = new Thread(() =>
{
Int32 iteration = 0;
while (true)
{
Console.WriteLine("Iteration {0}", iteration);
iteration++;
Thread.Sleep(1000);
if (cancToken.IsCancellationRequested)
break;
}
});
thread.Start();
Console.WriteLine("Press any key to cancel...");
Console.ReadKey();
cancTokenSource.Cancel();
3) You may want to read about interlocked class,monitor locks, autoresetevents and other synchronization, but they are not actually needed in this application
EDIT:
Well, I don't know how it couldn't help(it is not the best idea, but should work for such a scenario), so I'll try later to mock your app and check the issue - possibly it has something to do with how MSVC and CSC handle volatile specifier.
For now try to use Interlocked reads and writes in your app:
public ref class MeshCreator
{
private:
System::Boolean m_StopMesh;
...
}
STDMETHODIMP MeshCreator::CancelMesh(void)
{
Interlocked::Exchange(%(this->m_StopMesh), true);
return S_OK;
}
void MeshCreator::ProcessMesh(void)
{
Int32 processedParts = 0;
while(processedParts != totalPartsToProcess)
{
ContinueProcessing(processedParts);
processedParts++;
if (Interlocked::Read(%(this->m_StopMesh))
{
this->MakeCleanup();
MessageBox(NULL,aMessage,L"Test",NULL);
}
}
}
P.S.: Can you post the code that actually processes the data and checks the variable(I don't mean your full meshes calculations method, just its main stages and elements)?
EDIT: AT LEAST IT'S CLEAR WHAT THE SYSTEM IS ABOUT
It is possible that your child processes are just not exterminated quick enough. Read this SO thread about process killing.
P.S.: And edit your question to more clearly describe your system and problem. It is difficult to get the right answer to a wrong or incomplete question.

Try putting volatile before the field m_StopMesh:
volatile BOOL m_StopMesh;

I launched the c++ process using a thread and it worked fine.
If you want to communicate across process boundaries, you will need to use some sort of cross-process communication.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365574(v=vs.85).aspx
I find Named Pipes convenient and easy to use.
UPDATE
Your comment clarifies that the C++ code is running in-process.
I would suggest a ManualResetEvent. For a great overview of thread synchronization (and threads in general) check out http://www.albahari.com/threading/

Related

C#: is FileStream.ReadByte() a multi-threading friendly function?

So I have 16 threads that simultaneously run this method:
private void Work()
{
int currentByte;
char currentChar;
try
{
while (true)
{
position++;
currentByte = file.ReadByte();
currentChar = Convert.ToChar(currentByte);
entries.Add(new Entry(currentChar));
}
}
catch (Exception) { }
}
And then I have one more thread running this method:
private void ManageThreads()
{
bool done;
for(; ; )
{
done = !threads.Any(x => x.IsAlive == true);//Check if each thread is dead before continuing
if (done)
break;
else
Thread.Sleep(100);
}
PrintData();
}
Here is the problem: the PrintData method just prints everything in the 'entries' list to a text file. This text file is different every time the program is run even with the same input file. I am a bit of a noob when it comes to multi-threaded applications so feel free to dish out the criticism.
In general unless type explicitly calls out thread safety in its documentation you should assume it is not thread-safe*. Streams in .Net do not have such section and should be treated non-thread safe - use appropriate synchronization (i.e. locks) that guarantees that each stream is accessed from one thread at a time.
With file streams there is another concern - OS level file object may be updated from other threads - FileStream tries to mitigate it by checking if its internal state matches OS state - see FileStream:remarks section on MSDN.
If you want thread safe stream you can try to use Synchronized method as shown in C#, is there such a thing as a "thread-safe" stream?.
Note that code you have in the post will produce random results whether stream is thread safe or not. Thread safety of a stream will only guarantee that all bytes show up in output. If using non thread safe stream there is no guarantees at all and some bytes may show up multiple times, some skipped and any other behavior (crashes, partial reads,...) are possible.
* Thread-safe as in "internal state of the instance will be consistent whether it is called from one thread or multiple". It does not mean calling arbitrary methods from different threads will lead to useful behavior.

Make my COM assembly call asynchronous

I've just "earned" the privilege to maintain a legacy library coded in C# at my current work.
This dll:
Exposes methods for a big legacy system made with Uniface, that has no choice but calling COM objects.
Serves as a link between this legacy system, and another system's API.
Uses WinForm for its UI in some cases.
More visually, as I understand the components :
*[Big legacy system in Uniface]* ==[COM]==> [C# Library] ==[Managed API]==> *[Big EDM Management System]*
The question is: One of the methods in this C# Library takes too long to run and I "should" make it asynchronous!
I'm used to C#, but not to COM at all. I've already done concurrent programming, but COM seems to add a lot of complexity to it and all my trials so far end in either:
A crash with no error message at all
My Dll only partially working (displaying only part of its UI, and then closing), and still not giving me any error at all
I'm out of ideas and resources about how to handle threads within a COM dll, and I would appreciate any hint or help.
So far, the biggest part of the code I've changed to make my method asynchronous :
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
errMsg = "";
try {
Action<string> asyncOp = AsyncComparedSearch;
asyncOp.BeginInvoke(application, null, null);
} catch (ex) {
// ...
}
return 0;
}
private int AsyncComparedSearch(string application) {
// my actual method doing the work, that was the called method before
}
Any hint or useful resource would be appreciated.
Thank you.
UPDATE 1:
Following answers and clues below (especially about the SynchronizationContext, and with the help of this example) I was able to refactor my code and making it to work, but only when called from another Window application in C#, and not through COM.
The legacy system encounters a quite obscure error when I call the function and doesn't give any details about the crash.
UPDATE 2:
Latest updates in my trials: I managed to make the multithreading work when the calls are made from a test project, and not from the Uniface system.
After multiple trials, we tend to think that our legacy system doesn't support well multithreading in its current config. But that's not the point of the question any more :)
Here is a exerpt of the code that seems to work:
string application;
SynchronizationContext context;
// my public method called by the external system
public int ComparedSearch(string application, out string errMsg) {
this.application = application;
context = WindowsFormsSynchronizationContext.Current;
Thread t = new Thread(new ThreadStart(AsyncComparedSearchAndShowDocs));
t.Start();
errMsg = "";
return 0;
}
private void AsyncComparedSearch() {
// ANY WORK THAT AS NOTHING TO DO WITH UI
context.Send(new SendOrPostCallback(
delegate(object state)
{
// METHODS THAT MANAGE UI SOMEHOW
}
), null);
}
We are now considering other solutions than modifying this COM assembly, like encapsulating this library in a Windows Service and creating an interface between the system and the service. It should be more sustainable..
It is hard to tell without knowing more details, but there are few issues here.
You execute the delegate on another thread via BeginInvoke but you don't wait for it. Your try\catch block won't catch anything as it has already passed while the remote call is still being executed. Instead, you should put try\catch block inside AsyncComparedSearch.
As you don't wait for the end of the execution of remote method (EndInvoke or via callback) I am not sure how do you handle the results of the COM call. I guess then that you update the GUI from within AsyncComparedSearch. If so, it is wrong, as it is running on another thread and you should never update GUI from anywhere but the GUI thread - it will most likely result with a crash or other unexpected behavior. Therefore, you need to sync the GUI update work to GUI thread. In WinForms you need to use Control.BeginInvoke (don't confuse it with Delegate.BeginInvoke) or some other way (e.g. SynchronizationContext) to sync the code to GUI thread. I use something similar to this:
private delegate void ExecuteActionHandler(Action action);
public static void ExecuteOnUiThread(this Form form, Action action)
{
if (form.InvokeRequired) { // we are not on UI thread
// Invoke or BeginInvoke, depending on what you need
form.Invoke(new ExecuteActionHandler(ExecuteOnUiThread), action);
}
else { // we are on UI thread so just execute the action
action();
}
}
then I call it like this from any thread:
theForm.ExecuteOnUiThread( () => theForm.SomeMethodWhichUpdatesControls() );
Besides, read this answer for some caveats.

Proper way of passing a pointer for P/Invoke function

Dear skilled. I’m developing an entity which allows user to copy multiple files in async manner with cancellation ability (and reporting progress as well). Obviously the process of copying runs in another thread, different from thread where CopyAsync was called.
My first implementation uses FileStream.BeginRead/BeginWrite with a buffer and reporting progress against number of usages of that buffer.
Later, for education purposes, I was trying to implement the same stuff thru Win32 CopyFileEx function. Eventually, I’ve stumbled upon the following thing: this function takes a pointer to bool value which is treated as cancellation indicator. According to MSDN this value is to be examined multiple times by Win32 during copying operation. When user sets this value to “false” the copying operation is cancelled.
The real problem for me is how to create a boolean value, pass it to Win32 and to make this value accessible for external user to give him an ability to cancel the copying operation. Obviously the user will call CancelAsync(object taskId), so my question is about how to get access to that boolean value in another thread fro my CancelAsync implementation.
My first attempt was to use Dictionary where key is an identifier of async operation and value points to allocated for boolean value memory slot. When user calls “CancelAsync(object taskId)” method, my class retrieves a pointer to that allocated memory from dictionary and writes “1” there.
Yesterday I’ve developed another solution which is based on creating a bool local variable in my method of copying and holding the address of that value in dictionary until copying operation completes. This approach could be described in the following lines of code (very simple and rough, just to illustrate an idea):
class Program
{
// dictionary for storing operaitons identifiers
public Dictionary<string, IntPtr> dict = new Dictionary<string,IntPtr>();
static void Main(string[] args)
{
Program p = new Program();
p.StartTheThread(); // start the copying operation, in my
// implementation it will be a thread pool thread
}
ManualResetEvent mre;
public void StartTheThread()
{
Thread t = new Thread(ThreadTask);
mre = new ManualResetEvent(false);
t.Start(null);
GC.Collect(); // just to ensure that such solution works :)
GC.Collect();
mre.WaitOne();
unsafe // cancel the copying operation
{
IntPtr ptr = dict["one"];
bool* boolPtr = (bool*)ptr; // obtaining a reference
// to local variable in another thread
(*boolPtr) = false;
}
}
public void ThreadTask(object state)
{
// In this thread Win32 call to CopyFileEx will be
bool var = true;
unsafe
{
dict["one"] = (IntPtr)(&var); // fill a dictionary
// with cancellation identifier
}
mre.Set();
// Actually Win32 CopyFileEx call will be here
while(true)
{
Console.WriteLine("Dict:{0}", dict["one"]);
Console.WriteLine("Var:{0}", var);
Console.WriteLine("============");
Thread.Sleep(1000);
}
}
}
Actually I’m a bit new to P/Invoke and all unsafe stuff so hesitating about latter approach for holding a reference to local value in dictionary and exposing this value to another thread.
Any other thoughts on how to expose that pointer to boolean in order to support cancellation of copying operation?
Ah, so that's what that other thread was about. There's a much better way to accomplish this, CopyFileEx() also supports a progress callback. That callback allows you to update the UI to show progress. And it allows you to cancel the copy, just return PROGRESS_CANCEL from the callback.
Visit pinvoke.net for the callback delegate declaration you'll need.
If your goal is to support being able to cancel a file copy operation in progress, I recommend using a CopyProgressRoutine. This gets called regularly during the copy, and allows you to cancel the operation with a return code. It will let you cancel the operation asynchronously without having to deal with pointers directly.
private class FileCopy
{
private bool cancel = false;
public void Copy(string existingFile, string newFile)
{
if (!CopyFileEx(existingFile, newFile,
CancelableCopyProgressRoutine, IntPtr.Zero, IntPtr.Zero, 0))
{
throw new Win32Exception();
}
}
public void Abort()
{
cancel = true;
}
private CopyProgressResult CancelableCopyProgressRoutine(
long TotalFileSize,
long TotalBytesTransferred,
long StreamSize,
long StreamBytesTransferred,
uint dwStreamNumber,
CopyProgressCallbackReason dwCallbackReason,
IntPtr hSourceFile,
IntPtr hDestinationFile,
IntPtr lpData)
{
return cancel ? CopyProgressResult.PROGRESS_CANCEL :
CopyProgressResult.PROGRESS_CONTINUE;
}
// Include p/inovke definitions from
// http://www.pinvoke.net/default.aspx/kernel32.copyfileex here
}
If you do want to use the pbCancel argument, then manually allocating unmanaged memory as you are already doing is probably the safest way to do it. Taking the address of a local variable is a little dangerous because the pointer will no longer be valid once the variable goes out of scope.
You could also use a boolean field in an object rather than a boolean local variable, but you will need to pin it in memory to prevent the garbage collector from moving it. You can do this either using the fixed statement or using GCHandle.Alloc.
Perhaps I'm missing something, but why couldn't you just use the defn already # http://pinvoke.net/default.aspx/kernel32/CopyFileEx.html and then set the ref int (pbCancel) to 1 at cancel time?

Need help with weird Begin/EndInvoke issue which Causes "Thread Leak"

I got following code executing at a ~1000ms rate. Left alone, it causes a weird "thread leak". Using WindDBG/SoS I am able to see waaay to many ThreadPool Worker threads (some of them are marked as dead) and eventually I will get a AccessVioalation Exception. Can anybody tell me if my BeginInvoke/EndInvoke use is wrong, unnecessary lock perhaps ... any clues will help as I am ... well, clueless at this point
RichTextBox tmpBox = txtIncomingData;
lock (m_TextUpdateSynch) {
try {
result = Utilities.SafeBeginInvoke(this, delegate() {
try {
if (tmpBox.Text.Length > BufferSize) {
tmpBox.Text = rawData;
}
else {
tmpBox.AppendText(rawData);
}
pageBottom(txtIncomingData);
}
catch (...) {}
});
this.EndInvoke(result);
}
public static IAsyncResult Utilities.SafeBeginInvoke(System.ComponentModel.ISynchronizeInvoke control,
ControlUpdate action, AsyncCallback callback,
params object[] args) {
IAsyncResult result = null;
Control uiControl = control as Control;
try {
result = control.BeginInvoke(action, args);
}
catch (...) { }
return result;
}
It looks like your code is using WPF, and it's my understanding that in WPF BeginInvoke will marshall the call you;re making to the UI (Dispatcher) thread; so it shouldn't be creating any extra threads as far as I'm aware.
http://msdn.microsoft.com/en-us/library/ms591206.aspx
I notice your try/catch pairs around the BeginInvoke call too; this suggests to me that you've been getting exceptions thrown by that, and I'd suggest that getting to the root of them might be a better plan than suppressing them. For example you seem to be referencing three variables - BufferSize, rawData, txtIncomingData which are defined outside of your lock - if any other code has a reference to them and is modifying them on a different (non-UI) thread then that could be causing your issues.
Lastly, I think the overload of SafeBeginInvoke you listed isn't the one being called by the code - the one listed takes 4 parameters (although one is params), the one you call takes 2.

Using Named Mutex

I have two instances running of same Windows Service. They check the health of each other and report if any issue is found. I have a critical job that needs to be performed so I am running it with a fail-over approach, it runs in Master, and if Master is not responding it runs in slave. This job needs to communicate over a specific serial port, I am trying to use Mutex to check for race condition. I dont have access to production, so before deploying I want to make sure my approach is fine. So please suggest if my use of Mutex is fine for the given case.
if (iAmRunningInSlave)
{
HealthClient hc = new HealthClient();
if (!hc.CheckHealthOfMaster())
return this.runJobWrapper(withMutex, iAmRunningInSlave);
else
return true; //master is ok, we dont need to run the job in slave
}
return this.runJobWrapper(withMutex, iAmRunningInSlave);
And then in runJobWrapper
bool runJobWrapper(bool withMutex, bool iAmRunningInSlave)
{
if (!withMutex)
return this.runJob(iAmRunningInSlave); //the job might be interested to know
Mutex mutex = null;
string mutexName = this.jobCategory + "-" + this.jobTitle; //this will be unique for given job
try
{
mutex = Mutex.OpenExisting(mutexName);
return false; //mutex is with peer, return false which will re-trigger slave
}
catch
{
try
{ //mean time mutex might have created, so wrapping in try/catch
mutex = new Mutex(true /*initiallyOwned*/, mutexName);
return this.runJob(iAmRunningInSlave); //the job might be interested to know where I am running
}
finally
{
if (null!=mutex) mutex.ReleaseMutex();
}
return false;
}
}
I had a similar issue recently.
The design of the Mutex class is a bit weird/different from the normal classes in .NET.
Using OpenMutex to check for an existing Mutex is not really nice as you have to catch an exception.
A better approach is to use the
Mutex(bool initiallyOwned, string name, out bool createdNew)
constructor, and check the value returned by createdNew.
You don't look to check the return value from runJobWrapper anywhere - is this intentional? It is not obvious what the return value actually means anyway. Also you really shouldn't catch each any every exception that OpenExisiting could possibly throw - Out of memory? Stack overflow? etc. etc. Just catch the one you mean to handle correctly.
Also your code looks to be somewhat fragile - I wouldn't be surprised if you have race conditions.
I noticed that mutex.ReleaseMutex() was not releasing the mutex immediately..I had to call GC.Collect()

Categories