0

How to call method sendResponse to cross threaded call?

 void watcher_Created(object sender, FileSystemEventArgs e) {
            System.Diagnostics.Debug.WriteLine(e.FullPath);            
            sendResponse(e.FullPath); //this method must causes cross threaded call
        }

I was trying :

  Deployment.Current.Dispatcher.BeginInvoke(() => {                

            });

or Application.Current.Dispatcher.Invoke

But there is no Current .

How to deal with that?

I tried also:

        if (this.InvokeRequired) {...}

But there is no InvokeRequired.

EDIT I get unsupported exception when I create any object like Bitmap in sendResponse method. This method is called after firing event. So I thought it is crossthreading.

       void watcher_Created(object sender, FileSystemEventArgs e) {
            System.Diagnostics.Debug.WriteLine(e.FullPath);

            sendResponse(e.FullPath);
        }

 private void sendResponse(string path) {
            try {


                    BitmapImage bmi = new BitmapImage(new Uri(@path, UriKind.Relative));
                    byte[] data;
                    JpegBitmapEncoder encoder = new JpegBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(bmi));
                    using (MemoryStream ms = new MemoryStream()) {
                        encoder.Save(ms);
                        data = ms.ToArray();
                    }
                clientStream.Write(data, 0, data.Length);
            } catch (Exception e) { System.Diagnostics.Debug.WriteLine(e); }
        }

EDIT2 Client is widnows phone.. this(client) stopped worked after using code from the Nikita's answer(server stopped trhowing exceptions)

  try {
                            Deployment.Current.Dispatcher.BeginInvoke(() => {
                            MemoryStream stream = new MemoryStream(e.Buffer, e.Offset, e.BytesTransferred);


                                BitmapImage im = new BitmapImage();
                                im.SetSource(stream);

                                MainPage.page.imagePanel.Source = im;
                             });
  • 1
    What are you trying to do in send response? Is the file being passed in already a JPEG? BitmapImage is a WPF UI control, you shouldn't be using one in non UI code. There are probably better ways to accomplish what you are trying to do. – shf301 Feb 07 '14 at 11:35
  • What is the target platform? WPF? Windows Phone? – noseratio Feb 08 '14 at 04:42
  • @Noseratio Yes, it is Windows Phone 8. –  Feb 08 '14 at 09:08

2 Answers2

1

If you want to perform a call on UI thread, then you should save the reference to dispatcher by calling

 _dispatcher = Application.Current.Dispatcher;

on UI thread. Then you can access it on non-UI thread and use _dispatcher.BeginInvoke or _dispatcher.Invoke in your watcher_Created method.

If you simply want to make your code threadsafe - you can wrap the call in the lock statement:

private readonly object _sendLock = new object();

void watcher_Created(object sender, FileSystemEventArgs e) 
{
     System.Diagnostics.Debug.WriteLine(e.FullPath);            
     lock(_sendLock) 
     {
         sendResponse(e.FullPath);
     }
}

Edit: you do not need to use wpf components for opening a bitmap and you should not. Instead, for example, you can do the following:

using (MemoryStream ms = new MemoryStream())
using (Image img = Image.FromStream(File.OpenRead(@path)))
{
    img.Save(ms, ImageFormat.Jpeg);
    var data = ms.ToArray();
    clientStream.Write(data, 0, data.Length);
}
Nikita B
  • 3,303
  • 1
  • 23
  • 41
  • My Application has no `Current` anywhere. Please look at my edit of OP pleeeeaaaase. –  Feb 07 '14 at 11:20
  • This bitmap has to be converted to bytes. Where did I use WPF controls to open a bitmap? That could be helpfull. I do not want to save –  Feb 07 '14 at 11:45
  • 1
    @Yoda, replace a file stream with memory stream then, doesnt make much difference – Nikita B Feb 07 '14 at 11:46
  • I made a mistake in explaining. I need to open a jpg file then convert it to byte[] buffer then send it over TCP. It works but only once ;p i get these exceptions./ Could you show the alternative. I am not lying..(lie) I work straight for 48 hours no sleep. I am little slow now. –  Feb 07 '14 at 11:47
  • I open the file then put it in byty[] array. Then send the array. –  Feb 07 '14 at 11:51
  • 1
    @Yoda you open a bitmap file, conver it to jpg, and then send it. If that is what you need, look at example in my answer. – Nikita B Feb 07 '14 at 11:56
  • Now the exceptions on the sender side dissapeared but now the images on receiver side are not displayed(WindowsPhone) Before change the first sent was displayed, rest was not. EDIT2 –  Feb 07 '14 at 12:16
0

I don't have much of experience with WP8, but I think you should be able to use synchronization context, which is a universal concept. When your ViewModel or a UI element is created on the UI thread, remember the thread's current synchronization context:

SynchronizationContext _uiSyncContext;

// ...
_uiSyncContext = SynchronizationContext.Current;

Later from the background thread, use SynchronizationContext.Post (asynchronous callback) or SynchronizationContext.Send (synchronous callback) to execute code on the UI thread:

_uiSyncContext.Post((_) => { this.textBox.Text = "Hello"; }, null);
noseratio
  • 59,932
  • 34
  • 208
  • 486