This project has moved and is read-only. For the latest updates, please go here.
1

Closed

"No Source Available" + SyncContext is null?

description

Hi Scordo. Thanks for making this project available for everyone including myself.

I am making a console application in C#.NET and I am getting very strange issues.

I have managed to connect to a server just fine, also managed to send the login command and register for some notifications.

Issue is, whenever the notification event fires, I get a null exception along with visual studio trying to open the following path:

Locating source for 'c:\Projects\Codeplex\02\TS3QueryLib\Releases\V_1_0_5_0\TS3QueryLib.Core.Silverlight\TcpDispatcherBase.cs'. Checksum: MD5 {a 28 33 bc e0 6 c1 62 29 32 52 39 d7 eb a3 52}

Leading to "No Source Available". What I've learned so far is that the following code in TcpDispatcherBase.cs is causing issues:
        protected void OnNotificationReceived(object notificationText)
        {
            if (NotificationReceived != null)
                SyncContext.Post(p => NotificationReceived(((object[])p)[0], new EventArgs<string>(Convert.ToString(((object[])p)[1]))), new[] { this, notificationText });
        }
Exception is a System.NullReferenceException referring to SyncContext being null.

I found another bit of line that sets SyncContext to SynchronizationContext.Current but that one is also null.

After some googling, I found out that this might be because I am not running an UI. Is this the case here?

Would be very thankful for help on this. I have attached my code. It is reproduced by getting a notification that someone changes channel (for example).

file attachments

Closed Apr 13, 2014 at 5:21 PM by Scordo

comments

qvazzler wrote Apr 3, 2014 at 6:35 PM

Hello again.

I just tried executing the same code in a Forms application, and now it works just fine.

Is there a way for me to not have to use an UI application? I would just prefer a console. :-)

Scordo wrote Apr 4, 2014 at 5:21 AM

Hi qvazzler,

try putting the [MTAThread] Attribute at your Main-Method in the console application. This should do the trick.

Regards,
Scordo

Scordo wrote Apr 4, 2014 at 5:29 AM

^^ This does not work - sorry. I'll try to find another quickfix

Scordo wrote Apr 4, 2014 at 5:36 AM

OK, at the beginning of you console app sett the SyncContext like this:
SynchronizationContext.SetSynchronizationContext(new SingleThreadSynchronizationContext());
The Required class:
public sealed class SingleThreadSynchronizationContext : SynchronizationContext
{
    private readonly BlockingCollection<KeyValuePair<SendOrPostCallback, object>> m_queue = new BlockingCollection<KeyValuePair<SendOrPostCallback, object>>();
    private readonly Thread m_thread = Thread.CurrentThread;

    public override void Post(SendOrPostCallback d, object state)
    {
        if (d == null) throw new ArgumentNullException("d");
        m_queue.Add(new KeyValuePair<SendOrPostCallback, object>(d, state));
    }

    public override void Send(SendOrPostCallback d, object state)
    {
        throw new NotSupportedException("Synchronously sending is not supported.");
    }

    public void RunOnCurrentThread()
    {
        foreach (var workItem in m_queue.GetConsumingEnumerable())
            workItem.Key(workItem.Value);
    }

    public void Complete() { m_queue.CompleteAdding(); }
}
This was taken from here.

qvazzler wrote Apr 12, 2014 at 3:07 PM

Thank you Scordo, this made it work!

Also for others who stumble upon this; I had to add the following to the top of my .cs file:

using System.Threading;
using System.IO;
using System.Collections.Concurrent;

Please mark this as resolved.

qvazzler wrote Apr 12, 2014 at 5:43 PM

Hmm, I might have spoken too soon.

My events stop working when I make the change as you instructed.

I removed the code above and then the events started working again (for example atd_NotificationReceived).

Any ideas? :-)

qvazzler wrote Apr 12, 2014 at 5:56 PM

Ok, strange but it seems the fix was easy..

Instead of putting this:
SynchronizationContext.SetSynchronizationContext(new SingleThreadSynchronizationContext());
I made it like this:
SynchronizationContext ctx = new SynchronizationContext();
SynchronizationContext.SetSynchronizationContext(ctx);
This was in the Main function by the way.

wrote Apr 13, 2014 at 5:21 PM