How to use Thread in the button below - c#

When I press the button, decoding a Qrcode works well but I want to do it with a Thread.
I wrote like below but the thread doesn't work.
Does anyone know, how can i fix it?
Thanks.
Here is my code:
private async void button2_Click(object sender, EventArgs e)
{
await Task.Run(() =>
{
pictureBox1.Image = Image.FromFile(#"C:\Users...\1.jpg");
MessagingToolkit.QRCode.Codec.QRCodeDecoder decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
textBox2.Text = decoder.Decode(new QRCodeBitmapImage(pictureBox1.Image as Bitmap));
});
}

This will keep your UI responsive
private async void button2_Click(object sender, EventArgs e)
{
var Result = await Decode("Image Path");
textBox2.Text = Result;
}
private async Task<string> Decode(string PathOfImage)
{
var DecodedText = string.Empty;
var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
await Task.Run(() =>
{
DecodedText = decoder.Decode(new QRCodeBitmapImage(Image.FromFile(PathOfImage) as Bitmap));
});
return DecodedText;
}
Update 2 : here is how you can do it in one function :
private async void button2_Click(object sender, EventArgs e)
{
var DecodedText = string.Empty;
var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
await Task.Run(() => {
DecodedText = decoder.Decode(new QRCodeBitmapImage(Image.FromFile(PathOfImage) as Bitmap));
});
textBox2.Text = DecodedText;
}

You should update the TextBox after the completion of the Task, at a point where you are back to the UI thread.
private async void button2_Click(object sender, EventArgs e)
{
var bitmap = await Task.Run(() =>
{
return (Bitmap)Image.FromFile(#"C:\Users...\1.jpg");
});
pictureBox1.Image = bitmap;
var result = await Task.Run(() =>
{
var decoder = new MessagingToolkit.QRCode.Codec.QRCodeDecoder();
return decoder.Decode(new QRCodeBitmapImage(bitmap));
});
textBox2.Text = result;
}
Update: The code that updates the PictureBox should be moved out of the Task.Run body too.
Update: The loading of image can block the UI too, so I moved it in a separate Task.

The dispatcher object is used to modify the UI from a thread or a Task
Below how to use a Task
Method 1
bool result ;
Task<bool> task = Task.Run<bool>(async () => await RefreshUIAsync());
str = task.Result;
public async Task<bool> RefreshUIAsync()
{
bool result;
result= await Task.Factory.StartNew(() => RefreshUI());
return result;
}
private string RefreshUI()
{
bool result;
try
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
string ImagePath="";
pictureBox1.Image = Image.FromFile(ImagePath);
.......
});
result=true;
}
catch (Exception ex)
{
result=false;
}
return result;
}
Method 2
RefreshUIAsync().Wait();
public async Task RefreshUIAsync()
{
await Task.Run(() => {
This.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
string ImagePath="";
pictureBox1.Image = Image.FromFile(ImagePath);
.......
});
});
}
And below how to use a Thread
Method 1
myThread = new Thread(() => ThreaRefreshUI());
myThread.Start();
private void ThreaRefreshUI()
{
try
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
string ImagePath="";
pictureBox1.Image = Image.FromFile(ImagePath);
.......
});
}
catch (Exception ex)
{
}
}
Method 2
Thread thread = new Thread(new ThreadStart(ThreaRefreshUI));
thread.Start();
public void ThreaRefreshUI()
{
try
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
string ImagePath="";
pictureBox1.Image = Image.FromFile(ImagePath);
.......
});
}
catch (Exception ex)
{
}
}
Method 3
Thread thread = new Thread(ThreaRefreshUI);
thread.Start();
public void ThreaRefreshUI()
{
try
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate()
{
string ImagePath="";
pictureBox1.Image = Image.FromFile(ImagePath);
.......
});
}
catch (Exception ex)
{
}
}

Related

How to call a function in a backgroundworker thread that is to be completed on the main UI thread? [duplicate]

So, first I have read a ton of threads on this particular problem and I still do not understand how to fix it. Basically, I am trying to communicate with a websocket and store the message received in an observable collection that is bound to a listview. I know that I am getting a response back properly from the socket, but when it tries to add it to the observable collection it gives me the following error:
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
I've read some information on "dispatch" as well as some other things, but I am just massively confused! Here is my code:
public ObservableCollection<string> messageList { get; set; }
private void MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
string read = "";
try
{
using (DataReader reader = args.GetDataReader())
{
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
read = reader.ReadString(reader.UnconsumedBufferLength);
}
}
catch (Exception ex) // For debugging
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add your specific error-handling code here.
}
if (read != "")
messageList.Add(read); // this is where I get the error
}
And this is the binding:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
//await Authenticate();
Gameboard.DataContext = Game.GameDetails.Singleton;
lstHighScores.ItemsSource = sendInfo.messageList;
}
How do I make the error go away while still binding to the observable collection for my listview?
This solved my issue:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
}
);
Correct way to get the CoreDispatcher in a Windows Store app
Try replacing
messageList.Add(read);
with
Dispatcher.Invoke((Action)(() => messageList.Add(read)));
If you're calling from outside your Window class, try:
Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
Slight modification for task based async methods but the code in here will not be awaited.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
}
).AsTask();
This code WILL await, and will allow you to return a value:
private async static Task<string> GetPin()
{
var taskCompletionSource = new TaskCompletionSource<string>();
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
var pin = await UI.GetPin();
taskCompletionSource.SetResult(pin);
}
);
return await taskCompletionSource.Task;
}
And on Android:
private async Task<string> GetPin()
{
var taskCompletionSource = new TaskCompletionSource<string>();
RunOnUiThread(async () =>
{
var pin = await UI.GetPin();
taskCompletionSource.SetResult(pin);
});
return await taskCompletionSource.Task;
}
Maby this is not a "good" practice, but it works.. I leave a message from webSocket, to mainBody instance, where I have a timered reader...
public class C_AUTHORIZATION
{
public Observer3.A_MainPage_cl parentPageInstance; //еще одни экземпляр родителя
public WebSocket x_Websocket;
private string payload = "";
private DateTime nowMoment = DateTime.Now;
public void GET_AUTHORIZED()
{
bitfinex_Websocket= new WebSocket("wss://*****.com/ws/2");
var apiKey = "";
var apiSecret = "";
DateTime nowMoment = DateTime.Now;
payload = "{}";
x_Websocket.Opened += new EventHandler(websocket_Opened);
x_Websocket.Closed += new EventHandler(websocket_Closed);
}
void websocket_Opened(object sender, EventArgs e)
{
x_Websocket.Send(payload);
parentPageInstance.F_messager(payload);
}
void websocket_Closed(object sender, EventArgs e)
{
parentPageInstance.F_messager("L106 websocket_Closed!");
GET_AUTHORIZED();
}
}
public sealed partial class A_MainPage_cl : Page
{
DispatcherTimer ChartsRedrawerTimer;
public bool HeartBeat = true;
private string Message;
public A_MainPage_cl()
{
this.InitializeComponent();
ChartsRedrawerTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 100) };
ChartsRedrawerTimer.Tick += Messager_Timer;
ChartsRedrawerTimer.Start();
}
private void Messager_Timer(object sender, object e)
{
if(Message !=null) //
{
F_WriteLine(Message);
Message = null; //
}
}
public void F_messager(string message) //
{
Message = message;
}
In Xamarin, I got around this by using:
Device.BeginInvokeOnMainThread(() => {
// code goes here
});

Performace of multi-thread webbrowser control in ASP.NET Application

We have a .aspx page to programmatically load page content of up to 5 urls and check each for a keyword. The following code is working but need to improve cpu usage and time performance and I am not an expert in this area
First: use of async web form to wait for the urls
protected void Page_Load(object sender, EventArgs e)
{
//the page won't load till the registered task is completed
RegisterAsyncTask(new PageAsyncTask(ProcessURLsKeywords));
}
Second: create task for each url-keyword pair and wait for them all to finish then proceed to return page response
private async Task ProcessURLsKeywords()
{
List<Task> availableTasks = new List<Task>();
failedURLs = new ConcurrentBag<string>(); //thread-safe collection of unordered items
//start checking each keyword-url pair
if (key1 != null && !string.IsNullOrWhiteSpace(url1))
{
availableTasks.Add(CheckPageContent(url1, key1));
}
//do the same for url2,key2 and url3,key3...etc
await Task.WhenAll(availableTasks.ToArray());
//return response
}
Third: Function get content
private async Task CheckPageContent(string url, string key)
{
try
{
string content;
var browser = new WebProcessor();
content = await browser.GetGeneratedHTML(url);
if (content != null)
{
if (!content.ToLower().Contains(key.ToLower()))
{
failedURLs.Add(url);
}
}
content = null;
}
catch (Exception ex)
{
}
}
WebProcessor Class creates STA thread for each url and return the result
public class WebProcessor
{
private string GeneratedSource { get; set; }
private string URL { get; set; }
private MyWebBrowser wb { get; set; }
private static Mutex mutex = new Mutex();
public async Task<string> GetGeneratedHTML(string url)
{
URL = url;
await Task.Run(() =>
{
Thread t = new Thread(new ThreadStart(WebBrowserThread));
t.SetApartmentState(ApartmentState.STA);
t.Start();
t.Join();
});
return GeneratedSource;
}
private void WebBrowserThread()
{
mutex.WaitOne();
wb = new MyWebBrowser();
try
{
wb.AllowNavigation = true;
wb.ScriptErrorsSuppressed = true;
wb.Navigate(URL);
wb.DocumentCompleted +=
new WebBrowserDocumentCompletedEventHandler(
wb_DocumentCompleted);
while (wb.ReadyState != WebBrowserReadyState.Complete)
Application.DoEvents();
//Added this line, because the final HTML takes a while to show up
GeneratedSource = wb.DocumentText;
//GeneratedSource = wb.Document.Body.InnerText;
}
catch (Exception ex)
{
}
finally
{
mutex.ReleaseMutex();
wb.Dispose();
}
}
private void wb_DocumentCompleted(object sender,
WebBrowserDocumentCompletedEventArgs e)
{
try
{
MyWebBrowser wb = (MyWebBrowser)sender;
if (wb.ReadyState != System.Windows.Forms.WebBrowserReadyState.Complete)
return;
if (wb.Document == null)
return;
GeneratedSource = wb.Document.Body.InnerText;
//load frame content within page - web browser doesn't do that automatically
foreach (var frame in wb.Document.Window.Frames)
{
HtmlWindow winframe = frame as HtmlWindow;
WebProcessor webFrame = new WebProcessor();
try
{
System.Threading.SynchronizationContext.Current.Post(async delegate
{
try
{
GeneratedSource += await webFrame.GetGeneratedHTML(winframe.Url.AbsoluteUri);
}
catch (Exception ex)
{
}
}, null);
}
catch (Exception ex)
{
}
}
}
catch (Exception ex)
{
}
}
/*********************************************************************************************/
}
I tried integrating Application.Run() and message pump features but the code blocks on Application.Run()

Call UWP AppService on winform/wpf client

When i call AppService on UWP app, the AppServiceConnectionStatus returns Success.
But, when i call AppService on winform or wpf client, the AppServiceConnectionStatus still return AppServiceUnavailable.
UWP,Winform,WPF,the client code are the same:
private AppServiceConnection appService;
private async void ConnectServer()
{
if (appService == null)
{
appService = new AppServiceConnection();
appService.AppServiceName = "AserSecurityService";
appService.PackageFamilyName = "AserSecurityService_gfeg8w3smza92";
var status = await this.appService.OpenAsync();
if (status != AppServiceConnectionStatus.Success)
{
appService = null;
return;
}
}
}
The service code below:
public sealed class AserSecurityComponentProviderTask : IBackgroundTask
{
private BackgroundTaskDeferral backgroundTaskDeferral;
private AppServiceConnection appServiceconnection;
public void Run(IBackgroundTaskInstance taskInstance)
{
this.backgroundTaskDeferral = taskInstance.GetDeferral();
taskInstance.Canceled += OnTaskCanceled;
var details = taskInstance.TriggerDetails as AppServiceTriggerDetails;
appServiceconnection = details.AppServiceConnection;
appServiceconnection.RequestReceived += OnRequestReceived;
}
private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args)
{
var requestDeferral = args.GetDeferral();
try
{
var message = args.Request.Message;
var result = new ValueSet();
if (message.ContainsKey("HardwareID"))
{
result.Add("HardwareID", GetHardwareID());
}
await args.Request.SendResponseAsync(result);
}
catch (Exception ex)
{
var result = new ValueSet();
result.Add("exception", ex);
await args.Request.SendResponseAsync(result);
}
finally
{
requestDeferral.Complete();
}
}
private void OnTaskCanceled(IBackgroundTaskInstance sender, BackgroundTaskCancellationReason reason)
{
if (this.backgroundTaskDeferral != null)
{
this.backgroundTaskDeferral.Complete();
}
}
private string GetHardwareID()
{
if (Windows.Foundation.Metadata.ApiInformation.IsTypePresent("Windows.System.Profile.HardwareIdentification"))
{
var token = HardwareIdentification.GetPackageSpecificToken(null);
var hardwareId = token.Id;
var dataReader = Windows.Storage.Streams.DataReader.FromBuffer(hardwareId);
byte[] bytes = new byte[hardwareId.Length];
dataReader.ReadBytes(bytes);
return BitConverter.ToString(bytes).Replace("-", "");
}
throw new Exception("NO API FOR DEVICE ID PRESENT!");
}
}
How can I solve this issue?
or you can download my sample project code zip from
here or otherLink.

Cannot await 'Void' even when using Task

I have a problem. I am trying to modify an app I made some time ago and it Works still on WP Phone, but now I try to run it get these errors:
On await I get:
cannot await 'void'.
When I change void to task the error is still
Cannot await 'void'
I don't even have void any more.
Can somebody help me ?
namespace StreamUploadDownload
{
using System.Threading;
public partial class Page1 : PhoneApplicationPage
{
private PhotoCamera _cam;
private double _canvasWidth;
private double _canvasHeight;
private MediaLibrary _library = new MediaLibrary();
public int count = 100;
private static readonly string[] scopes = new string[] { "wl.signin", "wl.basic", "wl.offline_access", "wl.skydrive_update", "wl.skydrive" };
string comboValue;
private LiveConnectClient liveClient;
public int x = 0;
public int y = 0;
public string FileText { get; set; }
public int ComboNumber { get; set; }
public int ConnectionOK { get; set; }
public Page1()
{
InitializeComponent();
}
private void OnSessionChanged(object sender, LiveConnectSessionChangedEventArgs e)
{
this.liveClient = (e.Status == LiveConnectSessionStatus.Connected) ? new LiveConnectClient(e.Session) : null;
if (e.Status == LiveConnectSessionStatus.Connected)
{
btnSignin.Visibility = Visibility.Collapsed;
Pildista.Visibility = Visibility.Visible;
//Pildista2K.Visibility = Visibility.Visible;
Pildista.Content = "Pildista";
}
else
{
Pildista.Visibility = Visibility.Collapsed;
//Pildista2K.Visibility = Visibility.Collapsed;
btnSignin.Visibility = Visibility.Visible;
}
}
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if ((PhotoCamera.IsCameraTypeSupported(CameraType.Primary) == true) ||
(PhotoCamera.IsCameraTypeSupported(CameraType.FrontFacing) == true))
{
if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
{
_cam = new Microsoft.Devices.PhotoCamera(CameraType.Primary);
_cam.Initialized += new EventHandler<CameraOperationCompletedEventArgs>(cam_Initialized);
_cam.CaptureImageAvailable += new EventHandler<ContentReadyEventArgs>(cam_CaptureImageAvailable);
viewfinderBrush.SetSource(_cam);
//CameraButtons.ShutterKeyPressed += OnButtonFullPress;
base.OnNavigatedTo(e);
if (PhoneApplicationService.Current.State.ContainsKey("Text"))
{
txtvalue.Text = (string)PhoneApplicationService.Current.State["Text"];
FileText = txtvalue.Text;
}
if (PhoneApplicationService.Current.State.ContainsKey("index"))
{
ComboNumber = (int)PhoneApplicationService.Current.State["index"];
}
else
{
// The camera is not supported on the device.
this.Dispatcher.BeginInvoke(delegate()
{
// Write message.
});
// Disable UI.
AFButton.IsEnabled = false;
}
}
}
}
private double GetCameraAspectRatio()
{
IEnumerable<Size> resList = _cam.AvailableResolutions;
if (resList.Count<Size>() > 0)
{
Size res = resList.ElementAt<Size>(0);
return res.Width / res.Height;
}
return 1;
}
void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
{
if (e.Succeeded)
{
this.Dispatcher.BeginInvoke(delegate()
{
_canvasHeight = Application.Current.Host.Content.ActualWidth;
_canvasWidth = _canvasHeight * GetCameraAspectRatio();
viewfinderCanvas.Width = _canvasWidth;
viewfinderCanvas.Height = _canvasHeight;
});
}
}
//Failinime andmine ning salvestamine.
private async void cam_CaptureImageAvailable(object sender, Microsoft.Devices.ContentReadyEventArgs e)
{
if (ComboNumber == 1)
{
comboValue = "O";
}
if (ComboNumber == 2)
{
comboValue = "T";
}
if (ComboNumber == 3)
{
comboValue = "S";
}
if (ComboNumber == 4)
{
comboValue = "P";
}
if (ComboNumber == 5)
{
comboValue = "A";
}
if (ComboNumber == 6)
{
comboValue = "M";
}
string fileName = String.Format(FileText + "_" + comboValue + "_" + DateTime.Now.ToString("dd-MM-yyyy_HH-mm-ss") + ".jpg");
try
{
LiveOperationResult operationResult = await this.liveClient.UploadAsync("/me/skydrive", fileName, e.ImageStream, OverwriteOption.Overwrite); //Cannot await 'void'
}
catch (LiveConnectException ex)
{
// e.ImageStream.Close();
// this.infoTextBlock.Text = "Error getting contact info: ";
// this.infoTextBlock.Visibility = Visibility.Visible;
}
finally
{
e.ImageStream.Close();
y++;
Dispatcher.BeginInvoke(delegate()
{
string b = Convert.ToString(y);
loobvalue2.Text = b;
});
}
}
//kaameranupu vajutus.
private void takephoto_Click(object sender, RoutedEventArgs e)
{
if (_cam != null)
{
_cam.CaptureImage();
x++;
string s = x.ToString();
loobvalue.Text = s;
}
}
// Ühenduse Loomine. Session load.
private async void connectButton_Click(object sender, RoutedEventArgs e)
{
bool connected = false;
try
{
var authClient = new LiveAuthClient("RemovedforWeb");
LiveLoginResult result = await authClient.LoginAsync(new string[] { "wl.signin", "wl.skydrive" }); // cannot await 'void'
if (result.Status == LiveConnectSessionStatus.Connected)
{
connected = true;
var connectClient = new LiveConnectClient(result.Session);
var meResult = await connectClient.GetAsync("me");
dynamic meData = meResult.Result; //cannot await 'void'
}
else
{
//btnSignin.Visibility = Visibility.Visible;
}
}
catch (LiveAuthException ex)
{
}
EDIT: I added more code, and commented on problematic places
public async Task Method1 ()
{
}
public async Task<int> Method2 ()
{
}
For the above code, "Method1" does not return any value, whereas "Method2" returns an "int" value.
int i = await Method2(); //this is correct
await Method2(); //this is correct
int i = await Method1(); //this is NOT correct
await Method1(); //this is also correct
For the following line of code
LiveOperationResult operationResult = await this.liveClient.UploadAsync("/me/skydrive", fileName, e.ImageStream, OverwriteOption.Overwrite); //Cannot await 'void'
The "UploadAsync" method does not return any value, that's what it seems if you say "Cannot await 'void'"
Try removing "LiveOperationResult operationResult =" from the line of code and just write -
await this.liveClient.UploadAsync("/me/skydrive", fileName, e.ImageStream, OverwriteOption.Overwrite);
Same for the second line of code-
LiveLoginResult result = await authClient.LoginAsync(new string[] { "wl.signin", "wl.skydrive" }); // cannot await 'void'
Re-Write it as-
await authClient.LoginAsync(new string[] { "wl.signin", "wl.skydrive" }); // cannot await 'void'

The application called an interface that was marshalled for a different thread - Windows Store App

So, first I have read a ton of threads on this particular problem and I still do not understand how to fix it. Basically, I am trying to communicate with a websocket and store the message received in an observable collection that is bound to a listview. I know that I am getting a response back properly from the socket, but when it tries to add it to the observable collection it gives me the following error:
The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))
I've read some information on "dispatch" as well as some other things, but I am just massively confused! Here is my code:
public ObservableCollection<string> messageList { get; set; }
private void MessageReceived(MessageWebSocket sender, MessageWebSocketMessageReceivedEventArgs args)
{
string read = "";
try
{
using (DataReader reader = args.GetDataReader())
{
reader.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf8;
read = reader.ReadString(reader.UnconsumedBufferLength);
}
}
catch (Exception ex) // For debugging
{
WebErrorStatus status = WebSocketError.GetStatus(ex.GetBaseException().HResult);
// Add your specific error-handling code here.
}
if (read != "")
messageList.Add(read); // this is where I get the error
}
And this is the binding:
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
//await Authenticate();
Gameboard.DataContext = Game.GameDetails.Singleton;
lstHighScores.ItemsSource = sendInfo.messageList;
}
How do I make the error go away while still binding to the observable collection for my listview?
This solved my issue:
Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
}
);
Correct way to get the CoreDispatcher in a Windows Store app
Try replacing
messageList.Add(read);
with
Dispatcher.Invoke((Action)(() => messageList.Add(read)));
If you're calling from outside your Window class, try:
Application.Current.Dispatcher.Invoke((Action)(() => messageList.Add(read)));
Slight modification for task based async methods but the code in here will not be awaited.
await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
() =>
{
// Your UI update code goes here!
}
).AsTask();
This code WILL await, and will allow you to return a value:
private async static Task<string> GetPin()
{
var taskCompletionSource = new TaskCompletionSource<string>();
CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
async () =>
{
var pin = await UI.GetPin();
taskCompletionSource.SetResult(pin);
}
);
return await taskCompletionSource.Task;
}
And on Android:
private async Task<string> GetPin()
{
var taskCompletionSource = new TaskCompletionSource<string>();
RunOnUiThread(async () =>
{
var pin = await UI.GetPin();
taskCompletionSource.SetResult(pin);
});
return await taskCompletionSource.Task;
}
Maby this is not a "good" practice, but it works.. I leave a message from webSocket, to mainBody instance, where I have a timered reader...
public class C_AUTHORIZATION
{
public Observer3.A_MainPage_cl parentPageInstance; //еще одни экземпляр родителя
public WebSocket x_Websocket;
private string payload = "";
private DateTime nowMoment = DateTime.Now;
public void GET_AUTHORIZED()
{
bitfinex_Websocket= new WebSocket("wss://*****.com/ws/2");
var apiKey = "";
var apiSecret = "";
DateTime nowMoment = DateTime.Now;
payload = "{}";
x_Websocket.Opened += new EventHandler(websocket_Opened);
x_Websocket.Closed += new EventHandler(websocket_Closed);
}
void websocket_Opened(object sender, EventArgs e)
{
x_Websocket.Send(payload);
parentPageInstance.F_messager(payload);
}
void websocket_Closed(object sender, EventArgs e)
{
parentPageInstance.F_messager("L106 websocket_Closed!");
GET_AUTHORIZED();
}
}
public sealed partial class A_MainPage_cl : Page
{
DispatcherTimer ChartsRedrawerTimer;
public bool HeartBeat = true;
private string Message;
public A_MainPage_cl()
{
this.InitializeComponent();
ChartsRedrawerTimer = new DispatcherTimer() { Interval = new TimeSpan(0, 0, 0, 0, 100) };
ChartsRedrawerTimer.Tick += Messager_Timer;
ChartsRedrawerTimer.Start();
}
private void Messager_Timer(object sender, object e)
{
if(Message !=null) //
{
F_WriteLine(Message);
Message = null; //
}
}
public void F_messager(string message) //
{
Message = message;
}
In Xamarin, I got around this by using:
Device.BeginInvokeOnMainThread(() => {
// code goes here
});

Categories

Resources