End of thread cycle after deletion

I am looking for a thread safety code in C # that will avoid two problems, if possible;

  • If the stream object is deleted at any time, the stream loop terminates perfectly.
  • When used by another class or form (in particular, a form), the developer using the class should not forget to include the form closing event and call dispose. For instance. Correct server stream processing

The thread calls a method that has the following while loop:

while (!Finished) { string request = ""; try { //Block until we have a message or we are terminated in dispose ** request = server.Recv(Encoding.Unicode); //Send a response to the sender so they know we received. server.Send(request, Encoding.Unicode); } catch (Exception e) { //Catch a termination error. if (e.Errno == ETERM) { break; } } syncContext.Post( new SendOrPostCallback(delegate(object state) { MessageHandler handler = OnMessage; if (handler != null) { handler(request); } }), null); } 

And now the utility looks like this:

 public void Dispose() { Finished = true; //Cause all blocking message requests and sends to terminate with exception ** FZMQConext.Dispose(); //Wait for the thread to finish up. FThread.Join(); GC.SuppressFinalize(this); } 

The problems that I see

  • My event could be called even if I delete my class, since the thread should end. It is reported that is called between try / catch and syncContext.Post (). How bad is that?
  • Is there a way to wrap this class, so the user should not forget to call dispose. Currently, if they do not work, the application waits for the thread to complete, which will never happen. Setting it to a background thread seems lazy.
+4
source share
1 answer

My event can be called even if I delete my class, since the thread must end. It is reported that is called between try / catch and syncContext.Post (). How bad is that?

It doesn't look so bad. Once you set Finished=true . he should complete the publication of the new delegate and then exit the loop. However, you may run into CPU caching issues with Finished . A CPU core running in a loop can read the cached Finished value after another thread has changed the value, so the loop may erroneously continue. To prevent this, you should create a private field that changes only through Interlocked , and a method that changes this field:

 private int _running = 1; public void Stop() { Interlocked.Exchange(ref _running, 0); } 

and the loop will work while( _running > 0) .

Is there a way to wrap this class so that the user should not forget to call dispose. Currently, if they do not work, the application waits for the thread to complete, which will never happen. Setting it to a background thread seems lazy.

There is really no general way to avoid the burden of customer disposition. But if this class should always be used, for example, by Winforms components, then you can write a constructor that accepts the parent component and subscribe to the Disposed event Disposed parent. Therefore, when a parent component (for example, a form) is placed, this object is also deleted:

 public MyClass(Component parent) { parent.Disposed += (s,e) => this.Dispose(); } 

(I would choose the finalizer as an option, because it does not say whether / when it will be launched.)

+1
source

Source: https://habr.com/ru/post/1432862/


All Articles