Results 1 to 18 of 18

Thread: [RESOLVED] SynchronizationContext Trouble

  1. #1

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Resolved [RESOLVED] SynchronizationContext Trouble

    Hey all,
    I'm trying to change/execute the example http://www.codeproject.com/KB/thread...onContext.aspx

    I think the problem may be in my translation to Vb....

    I've posted my project below. I'm getting a cross-threading error and I thought the point of all of this was to avoid that. (yes I realize I could just delegate... I'm trying to do something more complicated but am using this as a test bed)
    Thanks in advance...

    The following is just a form with a button and list box.

    Code:
    Imports System.Threading.Thread
    Imports System.Threading
    
    
    Public Class Form1
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
            ' let's see the thread id
            Dim id As Integer
            Dim uiContext As SynchronizationContext
            Dim thread As Thread
    
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Button1_Click thread: " + id.ToString)
            ' grab the sync context associated to this
            ' thread (the UI thread), and save it in uiContext
            ' note that this context is set by the UI thread
            ' during Form creation (outside of your control)
            ' also note, that not every thread has a sync context attached to it.
            uiContext = SynchronizationContext.Current
    
            ' create a thread and associate it to the run method
            thread = New Thread(AddressOf Run)
    
            ' start the thread, and pass it the UI context,
            ' so this thread will be able to update the UI
            ' from within the thread
            thread.Start(uiContext)
    
        End Sub
    
        Private Sub Run(ByVal state As Object)
    
            Dim id As Integer
            Dim uiContext As SynchronizationContext
    
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Run thread: " + id.ToString)
            ' grab the context from the state
            uiContext = state
            For i = 0 To 1000
                Thread.Sleep(10)
                ' use the ui context to execute the UpdateUI method,
                ' this insure that the UpdateUI method will run on the UI thread.
                uiContext.Post(UpdateUI(state), "line " + i.ToString())
            Next
    
        End Sub
    
       
        Private Function UpdateUI(ByVal state As Object)
            Dim id As Integer
            Dim text As String
            id = Thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("UpdateUI thread:" + id.ToString)
            text = state.ToString
            mListBox.Items.Add(text)
            Return ""
        End Function
    
    
    End Class

  2. #2
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: SynchronizationContext Trouble

    You don't need to pass the uiContext to the thread. Variables declared outside of methods are not tied to any particular thread, and are therefore accessible from any of them. Therefore, since uiContext was declared at class scope, the thread will see it just as well as any other code.

    EDIT: Oops, you declared the uiContext as a local variable. I assumed you had it at class scope because that is what I always do. In your case, passing it along seems like the reasonable thing to do, as I assume that you class scope wouldn't suffice.

    What are your traces showing you? Are they what you expect?

    Also, where are you getting the exception? I would guess that it is when you add to the listbox, as that is the only control you appear to be manipulating, but might as well be certain.
    My usual boring signature: Nothing

  3. #3
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    The first thing you should do is turn Option Strict On and leave it On for this and every other project. I just copied your code and fixed the errors that Option Strict On flagged and it worked fine.
    Code:
    Imports System.Threading.Thread
    Imports System.Threading
    
    
    Public Class Form1
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
            ' let's see the thread id
            Dim id As Integer
            Dim uiContext As SynchronizationContext
            Dim thread As Thread
    
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Button1_Click thread: " + id.ToString)
            ' grab the sync context associated to this
            ' thread (the UI thread), and save it in uiContext
            ' note that this context is set by the UI thread
            ' during Form creation (outside of your control)
            ' also note, that not every thread has a sync context attached to it.
            uiContext = SynchronizationContext.Current
    
            ' create a thread and associate it to the run method
            thread = New Thread(AddressOf Run)
    
            ' start the thread, and pass it the UI context,
            ' so this thread will be able to update the UI
            ' from within the thread
            thread.Start(uiContext)
    
        End Sub
    
        Private Sub Run(ByVal state As Object)
    
            Dim id As Integer
            Dim uiContext As SynchronizationContext
    
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Run thread: " + id.ToString)
            ' grab the context from the state
            uiContext = DirectCast(state, SynchronizationContext)
            For i = 0 To 1000
                Thread.Sleep(10)
                ' use the ui context to execute the UpdateUI method,
                ' this insure that the UpdateUI method will run on the UI thread.
                uiContext.Post(AddressOf UpdateUI, "line " + i.ToString())
            Next
    
        End Sub
    
    
        Private Function UpdateUI(ByVal state As Object) As String
            Dim id As Integer
            Dim text As String
            id = Thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("UpdateUI thread:" + id.ToString)
            text = state.ToString
            mListBox.Items.Add(text)
            Return ""
        End Function
    
    
    End Class
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  4. #4

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Turning it on from options didn't do anything. But when I added option strict on at the top it did an awesome job of showing me all that was wrong.

    Thanks so much!
    I'm adding it to all of my projects and am finding lots of casting errors.

  5. #5

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Last Question:
    If I had started another thread in this example and instead of jumping into the UI thread I wanted to jump into a previously created thread...
    i.e. in this call
    Code:
     uiContext = SynchronizationContext.Current
    What would I do if I wanted the SC of thread A, instead of the current UI thread?
    (here is the fictitious A code)

    Code:
     Dim A As Thread
            A = New System.Threading.Thread(AddressOf doThreadA)
            A.Start()

  6. #6
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    Whichever thread you get SynchronizationContext.Current on, that's the thread that that SynchronizationContext object will post to. If you create a new thread you can access SynchronizationContext.Current and assign the value to a variable, then other threads can use that variable to post method calls to that thread.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  7. #7

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Ok,
    Using your fixed example. (thank you again btw)
    I placed the call
    Code:
     testContext = SynchronizationContext.Current
    in the Run subroutine. This should be on the thread Thread. (wow that was a bad name...)
    But when I check it in runtime it gives a value of Nothing. (full code below)

    Code:
    Public Class Form1
        Private testContext As SynchronizationContext
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    
    
            ' let's see the thread id
            Dim id As Integer
            Dim uiContext As SynchronizationContext
            Dim thread As Thread
    
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Button1_Click thread: " + id.ToString)
            ' grab the sync context associated to this
            ' thread (the UI thread), and save it in uiContext
            ' note that this context is set by the UI thread
            ' during Form creation (outside of your control)
            ' also note, that not every thread has a sync context attached to it.
            uiContext = SynchronizationContext.Current
    
            ' create a thread and associate it to the run method
            thread = New Thread(AddressOf Run)
            thread.IsBackground = True
            ' start the thread, and pass it the UI context,
            ' so this thread will be able to update the UI
            ' from within the thread
            thread.Start(uiContext)
    
        End Sub
    
        Private Sub Run(ByVal state As Object)
    
            Dim id As Integer
            Dim uiContext As SynchronizationContext
            testContext = SynchronizationContext.Current
            id = thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("Run thread: " + id.ToString)
            ' grab the context from the state
            uiContext = DirectCast(state, SynchronizationContext)
            For i = 0 To 1000
                Thread.Sleep(10)
                ' use the ui context to execute the UpdateUI method,
                ' this insure that the UpdateUI method will run on the UI thread.
                uiContext.Post(AddressOf UpdateUI, "line " + i.ToString())
            Next
    
        End Sub
    
    
        Private Sub UpdateUI(ByVal state As Object)
            Dim id As Integer
            Dim text As String
            id = Thread.CurrentThread.ManagedThreadId
            Trace.WriteLine("UpdateUI thread:" + id.ToString)
            text = state.ToString
            mListBox.Items.Add(text)
        End Sub
    
    
    End Class

  8. #8
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    Interesting. I just did a bit of testing and it does indeed appear that accessing SynchronizationContext.Current on other than the UI thread retrieves a null reference. That's not what I expected but, I must admit, there were some assumptions at play. I'm not an expert on the SynchronizationContext class and it seems that noone else is either because information is scarce. That said, I can't think of a reason that you'd need to use it for other than the UI thread anyway.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  9. #9

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Your're right on the not really needing it. It was more of a desire to have a more logical flow of data. (kind of data collection in tree form rather than everything reporting to one huge collection class and wasting UI processing time.)

    Well, if anyone out there figures anything out I would appreciate it.

    This article references the situation but I'm not experienced enough to understand if he is just using it to sort out if the thread is a UI or not thread or if he has a solution that would work for my wants.

    Thanks again for taking the time to look at it all.

    http://daveonsoftware.blogspot.com/2...ioncontex.html

  10. #10
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    I'm not really sure what problem it is that you want a solution to.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  11. #11

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Basically I would really like to pass information from one thread to another with out any weird data synch problems.

    - Nick

  12. #12
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    Quote Originally Posted by nickwrs View Post
    Basically I would really like to pass information from one thread to another with out any weird data synch problems.

    - Nick
    But you can already do that. Passing information between threads is really no issue at all because, when we're talking about standard variables, all threads have access to all data all the time. The only real issue when it comes to threading is that you cannot access the handle of a control on any thread except the one on which it was created. That's really the only reason that you have to ensure that certain things are done on a specific thread. You've already got three ways to do that: the ISynchronizeInvoke interface in WinForms, the Dispatcher class in WPF and the SynchronizationContext class in either. Why do you need anything else?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  13. #13

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    I guess I was under the impression that if a class had more than one thread trying to access a class level variable at the same time a problem would occur.

    If that isn't true, then I have no problems at all....

    if it is true then I don't think I understood your last post. Sorry.

    Thanks again for bearing with me.

    - Nick

  14. #14
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    Quote Originally Posted by nickwrs View Post
    I guess I was under the impression that if a class had more than one thread trying to access a class level variable at the same time a problem would occur.

    If that isn't true, then I have no problems at all....

    if it is true then I don't think I understood your last post. Sorry.

    Thanks again for bearing with me.

    - Nick
    It is and it isn't. There's no issue having multiple threads accessing the same data. It happens all the time. What is a problem is if you have multiple threads reading and writing exactly the same data at exactly the same time, which can have serious consequences.

    Consider a situation where you have two threads that both get the value of a variable, add 1 to that value, then assign the result back to the variable. Because the order in which multiple threads execute is indeterminate, that situation might yield the correct result most of the time, but sometimes it will do the wrong thing. What if one thread reads the value and increments it but gets switched out before writing the result back to the variable? The second thread will come along and read the old value, increment it and write the result back, then the first thread will pick up again and write its result back. The variable's value will only increase by 1 instead of by 2, and that could be disastrous, depending on what your app does with the value.

    The solution to such issues has nothing to do with passing data between threads and everything to do with synchronising execution of threads. What you need to do is wrap the code that accesses the common data in a lock, such that a second thread can't enter the critical section before the first thread exits. This ensures that, in the case of the previous example, once a thread starts reading the variable, no other thread can read it until the first thread has written to it.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  15. #15

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Could a lock be as simple as a class level flag? don't change this variable unless this flag is true etc.

  16. #16
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: SynchronizationContext Trouble

    Quote Originally Posted by nickwrs View Post
    Could a lock be as simple as a class level flag? don't change this variable unless this flag is true etc.
    No, because the flag itself has the same problem. One thread comes along and reads the flag and sees it can continue and then gets preempted by a second thread that also reads the flag and continues. Both threads then toggle the flag and continue to access the common data. The flag itself is part of the common data so you've simply moved the probelm.

    Thread synchronisation functionality is built into the Framework and the language. The simplest form of synchronisation is the SyncLock statement.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  17. #17

    Thread Starter
    Hyperactive Member nickwrs's Avatar
    Join Date
    Jan 2000
    Location
    Atlanta, Ga
    Posts
    398

    Re: SynchronizationContext Trouble

    Got it. I'll look that up. Thanks again.

  18. #18
    Super Moderator Shaggy Hiker's Avatar
    Join Date
    Aug 2002
    Location
    Idaho
    Posts
    40,106

    Re: [RESOLVED] SynchronizationContext Trouble

    By the way, it is precisely the problem with that flag idea that lead to the Mutex, which is something like a kernel-level flag. You can find Mutexes in the framework, but Synclock and Monitor are much faster in practice. As for those two, Synclock is a Monitor wrapped in some error handling to ensure that the Monitor is released. So use a Synclock where you can, use a Monitor only where a Synclock won't work (which is quite rare), and use a Mutex only where neither of the other two will work. However, since a Mutex is a kernel level object, the places that it would be superior can be relatively easily enumerated: Those places where you need to synchronize data access between different running programs. Not a common scenario.
    My usual boring signature: Nothing

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width