Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>What is the best way to achieve what I want? Is it one of the two or another approach?</p> </blockquote> <p>Both look fine, but...</p> <blockquote> <p>Is one of the two ways not thread-safe (I fear both...) and why?</p> </blockquote> <p>...they are not thread safe <em>unless</em> <code>MyObject.ChangeSomeProperty()</code> is thread safe. </p> <blockquote> <p>The first approach creates a thread and passes it the object in the constructor. Is that how I'm supposed to pass the object?</p> </blockquote> <p>Yes. Using a closure (as in your second approach) is fine as well, with the additional advantage that you don't need to do a cast.</p> <blockquote> <p>The second approach uses a timer which doesn't provide that possibility, so I just use the local variable in the anonymous delegate. Is that safe or is it possible in theory that the reference in the variable changes before it is evaluated by the delegate code? (This is a very generic question whenever one uses anonymous delegates).</p> </blockquote> <p>Sure, if you add <code>myObject = null;</code> directly after setting <code>timer.Elapsed</code>, then the code in your thread will fail. But why would you want to do that? Note that changing <code>this.MyObject</code> will not affect the variable captured in your thread.</p> <hr> <p>So, how to make this thread-safe? The problem is that <code>myObject.ChangeSomeProperty();</code> might run in parallel with some other code that modifies the state of <code>myObject</code>. There are basically two solutions to that:</p> <p><strong>Option 1</strong>: Execute <code>myObject.ChangeSomeProperty()</code> in the main UI thead. This is the simplest solution if <code>ChangeSomeProperty</code> is fast. You can use the <code>Dispatcher</code> (WPF) or <code>Control.Invoke</code> (WinForms) to jump back to the UI thread, but the easiest way is to use a <code>BackgroundWorker</code>:</p> <pre><code>MyObject myObject = this.MyObject; var bw = new BackgroundWorker(); bw.DoWork += (sender, args) =&gt; { // this will happen in a separate thread Thread.Sleep(1000); DoTheCodeThatNeedsToRunAsynchronously(); } bw.RunWorkerCompleted += (sender, args) =&gt; { // We are back in the UI thread here. if (args.Error != null) // if an exception occurred during DoWork, MessageBox.Show(args.Error.ToString()); // do your error handling here else myObject.ChangeSomeProperty(); } bw.RunWorkerAsync(); // start the background worker </code></pre> <p><strong>Option 2</strong>: Make the code in <code>ChangeSomeProperty()</code> thread-safe by using the <code>lock</code> keyword (inside <code>ChangeSomeProperty</code> as well as inside any other method modifying or reading the same backing field).</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload