Reputation:
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;
});
Upvotes: 0
Views: 206
Reputation: 61736
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);
Upvotes: 0
Reputation: 3333
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);
}
Upvotes: 1