i want to know how to insert MobileServiceCollection from Windows Azure to my ObservableCollection from JSON web service
private ObservableCollection<AddressDetail> _hereRestAddressDetail = null;
public ObservableCollection<AddressDetail> hereRestAddressDetail
{
get { return _hereRestAddressDetail; }
set { this.SetProperty(ref this._hereRestAddressDetail, value); }
}
private async void UpdateTransportDetail()
{
try
{
WebClient client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
if (e.Error == null)
{
RootObjectDetail result = JsonConvert.DeserializeObject<RootObjectDetail>(e.Result);
hereRestAddressDetail.Clear();
hereRestAddressDetail.Insert(0,result);
}
else
{
isFailed = Visibility.Visible;
isFailedMessage = "Can't get data from web server, please refresh and make sure your internet data connected";
}
};
client.DownloadStringAsync(new Uri(hrefText + transportDetailURL));
hereRestAddressDetail = await addressTable.ToCollectionAsync();
}
catch (Exception)
{
isFailed = Visibility.Visible;
isFailedMessage = "Something wrong happen, please refresh";
}
}
and what i try to do is to add my azure data into the next entry of hereRestAddressDetail (since the first is from json web service) with this
hereRestAddressDetail = await addressTable.ToCollectionAsync();
but it just replace the data from json not adding it, how can i make it appear with my json data also?
Not sure if the question is still actual, but you can replace the while collection
hereRestAddressDetail = new ObservableCollection<AddressDetail>(await addressTable.ToCollectionAsync());
Or (i'd recommend this way) grab OptimizedObservableCollection ( for example, here: http://www.pedrolamas.com/2013/05/08/cimbalino-windows-phone-toolkit-updated-to-v2-3-0/ ) and use it like
hereRestAddressDetail.ReplaceWith(await addressTable.ToCollectionAsync()); // replace
or
hereRestAddressDetail.AddRange(await addressTable.ToCollectionAsync()); // add
Related
I have an async function which still freezes / lags the UI thread for me when I execute it. This is my function calling it.
private void TcpListenerLogic(object sender, string e)
{
Application.Current.Dispatcher.BeginInvoke((Action)async delegate {
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
// Get properties for new anchor
string testInformation = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + results.test_id);
}
}
catch (Exception exception)
{
// Writing some Trace.WriteLine()'s
}
});
}
And this is the async function that freezes my UI Thread
public static async Task<string> getJsonFromURL(string url)
{
try
{
string returnString = null;
using (System.Net.WebClient client = new System.Net.WebClient())
{
returnString = await client.DownloadStringTaskAsync(url);
}
return returnString;
}
catch (Exception ex)
{
Debug.WriteLine(ex.ToString());
return null;
}
}
I already tried to make everything in TcpListenerLogic run in a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
}).Start();
Which resulted in the whole UI completely freezing. And I tried to make TcpListenerLogic async and await the dispatcher, which also made everything freeze permanently. I also tried to make TcpListenerLogic async and leave the dispatcher. The dispatcher is only there because I normally have some UI code in there, which I left out for my tests.
I have ventured far through the internet, but no BackgroundWorker, ThreadPool or other methods helped me in my endeavour.
If anyone has help for this particular problem, or a resource that would improve my understanding of async functions in C#, I would much appreciate it.
Edit
As requested a deeper insight in how this event handler is called.
I have System.Net.Websocket, which is connected to the Backend API I am working with and triggers an event, everytime he receives new Data. To guarantee the socket listens as longs as it is open, there is a while loop which checks for the client state:
public event EventHandler<string> TcpReceived;
public async void StartListener(string ip, int port, string path)
{
try
{
using (client = new ClientWebSocket())
{
try
{ // Connect to backend
Uri serverUri = new Uri("ws://" + ip + ":" + port.ToString() + path );
await client.ConnectAsync(serverUri, CancellationToken.None);
}
catch (Exception ex)
{
BackendSettings.IsConnected = false;
Debug.WriteLine("Error connecting TCP Socket: " + ex.ToString());
}
state = client.State;
// Grab packages send in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
try
{
// **Just formatting the received data until here and writing it into the "message" variable**//
TcpReceived(this, message);
// Close connection on command
if (result.MessageType == WebSocketMessageType.Close)
{
Debug.WriteLine("Closing TCP Socket.");
shouldstayclosed = true;
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, string.Empty, CancellationToken.None);
break;
}
state = client.State;
}
catch
{
BackendSettings.IsConnected = false;
state = client.State;
}
}
state = client.State;
}
}
catch (Exception ex)
{
// Some error messages and settings handling
}
}
The Event has a handler attached:
TcpReceived += TcpListener_TcpReceived;
And this is the Handler, which calls the previously seen "TcpListenereLogic".
private void TcpListener_TcpReceived(object sender, string e)
{
TcpListenerLogic(sender, e);
//App.Current.Dispatcher.BeginInvoke(new Action(() => {
// TcpListenerLogic(sender, e);
//}));
//new Thread(() =>
//{
// Thread.CurrentThread.IsBackground = true;
// TcpListenerLogic(sender, e);
//}).Start();
}
I previously had the "TcpListenereLogic" as the handler, but I wanted to try different methods to call it. I also left in the commented out part, to show how the call of "TcpListenereLogic" looked already. All my attempts were with all mentioned setups and sadly lead to nothing.
Thank you very much #TheodorZoulias for helping me to find the solution to my problem.
It turns out it wasn't the async function itself, but rather how often it gets called. It got called roughly ~120 times every second.
My solution starts by calling the Listener method over a new Thread:
new Thread(() =>
{
Thread.CurrentThread.IsBackground = true;
MainWindow.tcpListener.StartListener(ip, portNumber, "/api/");
}).Start();
To limit the amount of calls that happen every second I added a dispatcher timer, that resets a bool after it has been used for a call, by my Event.
readonly System.Windows.Threading.DispatcherTimer packageIntervallTimer =
new System.Windows.Threading.DispatcherTimer();
bool readyForNewPackage = true;
private void ReadyForPackage(object sender, EventArgs e)
{
readyForNewPackage = true;
}
public async void StartListener(string ip, int port, string path)
{
packageIntervallTimer.Interval = TimeSpan.FromMilliseconds(50);
packageIntervallTimer.Tick += (s, e) => { Task.Run(() => ReadyForPackage(s, e)); };
packageIntervallTimer.Start();
Then I wrapped everything inside the while loop into an if condition based on the bool, the most important part was to have my "event EventHandler TcpReceived" in there:
// Grab packages sent in backend
while (client.State == WebSocketState.Open || client.State == WebSocketState.CloseSent)
{
if (readyForNewPackage == true)
{
readyForNewPackage = false;
try
{
....
TcpReceived(this, message);
....
}
catch
{
...
}
}
}
I added my TcpListenerLogic to the Eventhandler:
TcpReceived += TcpListenerLogic;
And my TcpListenerLogic now looked like this (names have been changed):
private async void TcpListenerLogic(object sender, string e)
{
try
{
dynamic results = JsonConvert.DeserializeObject<dynamic>(e);
if (results.test_id != null)
{
string testID = "";
if (results.test_id is JValue jValueTestId)
{
testID = jValueTestId.Value.ToString();
}
else if (results.test_id is string)
{
testID = results.test_id;
}
// Get properties for new object
string information = await CommunicationCommands.getJsonFromURL(
"http://" + ServerIP + ":" + ServerPort + "/api/" + testID );
if (information != null)
{
await App.Current.Dispatcher.BeginInvoke(new Action(() =>
{
// Create object out of the json string
TestStatus testStatus = new TestStatus();
testStatus.Deserialize(information);
if (CommunicationCommands.isNameAlreadyInCollection(testStatus.name) == false)
{
// Add new object to the list
CommunicationCommands.allFoundTests.Add(testStatus);
}
}));
{
}
catch (Exception exception)
{
....
}
}
Adding a new Thread to execute any step results in problems, so keep in mind that all this uses the thread created at the beginning for "StartListener"
Having this :
public Item_DataColl invoke_command_READ(string UCPTName)
{
networkingThread = new Thread(new ParameterizedThreadStart(thread_command_READ));
networkingThread.Start(new readingThreadParameter(UCPTName));
}
private Item_DataColl thread_command_READ_result(object parameter)
{
readingThreadParameter p = parameter as readingThreadParameter;
Item item;
if (p.UCPT_Name != null)
{
Item_DataColl resultSet;
try
{
OnProgressBarUpdate(progressBar.UnknownEnd);
resultSet = connector.command_READ(p.UCPT_Name);
readOperationDone(resultSet);
OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);
return resultSet; // HERE, I WANT TO RETURN RESULT
}
catch (Exception e)
{
OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
}
finally
{
OnProgressBarUpdate(progressBar.Invisible);
}
}
}
I'm trying to execute a SOAP request and to send the result. To make the application "non-blocking", i've used Thread.
The soap request works perfectly, but i have trouble to send a result just after the end of the thread. I will have to keep track of it and when the thread is over, to send back the result to another class.
How can i perform this ?
Well.. this solution CAN BE WRITTEN WAY BETTER.. but I'm currently working with the code you already posted.
The approach - using a callback (with a delegate):
First - declare a delegate in your class scope
private Action<Item_DataColl> OnResultSetComplete;
Second - assign the delegate with some function BEFORE calling your thread
public Item_DataColl invoke_command_READ(string UCPTName)
{
OnResultSetComplete = (resukts) =>
{
// DO SOMETHING HERE
};
networkingThread = new Thread(new ParameterizedThreadStart(thread_command_READ));
networkingThread.Start(new readingThreadParameter(UCPTName));
}
Finally - change your read result function:
private Item_DataColl thread_command_READ_result(object parameter)
{
readingThreadParameter p = parameter as readingThreadParameter;
Item item;
if (p.UCPT_Name != null)
{
Item_DataColl resultSet;
try
{
OnProgressBarUpdate(progressBar.UnknownEnd);
resultSet = connector.command_READ(p.UCPT_Name);
readOperationDone(resultSet);
OnConsoleWriting(string.Format("[READING] Lecture réussie : {0} = {1}", ((Dp_Data)resultSet.Item[0]).UCPTname, ((Dp_Data)resultSet.Item[0]).UCPTvalue[0].Value), ILonConnectorConsoleResultType.RESULT);
if (OnResultSetComplete != null) OnResultSetComplete(resultSet);
}
catch (Exception e)
{
OnConsoleWriting(e.ToString(), ILonConnectorConsoleResultType.ERROR);
}
finally
{
OnProgressBarUpdate(progressBar.Invisible);
}
}
}
I am currently working on Windows 8.1 Push Notification part. I have read different links and found that first we need to register the app and get all the information like SID and Client Secret and send to our server team so they can send push notification.
Then after this, I implemented the following code at my side to get channelUri and Expiration date of that Uri from WNS.
PushNotificationChannel channel = null;
try
{
channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
if (channel != null)
{
var notificationUri = channel.Uri;
var expiration_time = channel.ExpirationTime;
}
channel.PushNotificationReceived += channel_PushNotificationReceived;
}
catch (Exception ex)
{
if (ex != null)
{
System.Diagnostics.Debug.WriteLine(ex.HResult);
}
}
I have received all the values perfectly and my server team added a logic to send me push notification. Now, the problem which I am facing is that I am not aware how to display the received push notification sent by server to that user. Also, can we display the notification is the app is not running or is in background?
Background Tasks solved my problem.
First you need to create a WindowsRuntimeComponent Project and add the code below
public sealed class PushNotification:IBackgroundTask
{
public void Run(IBackgroundTaskInstance taskInstance)
{
RawNotification notification = (RawNotification)taskInstance.TriggerDetails as RawNotification;
if (notification != null)
{
ToastTemplateType toastTemplate = ToastTemplateType.ToastImageAndText01;
XmlDocument toastXml = ToastNotificationManager.GetTemplateContent(toastTemplate);
var textElemets = toastXml.GetElementsByTagName("text");
textElemets[0].AppendChild(toastXml.CreateTextNode(notification.Content));
var imageElement = toastXml.GetElementsByTagName("image");
imageElement[0].Attributes[1].NodeValue = "ms-appx:///Assets/50.png";
ToastNotificationManager.CreateToastNotifier().Show(new ToastNotification(toastXml));
}
}
}
Then register the background task in any of the page( i added in Home Page) using below code
private async void RegisterBackgroundTask()
{
await BackgroundExecutionManager.RequestAccessAsync();
try
{
foreach (var task in BackgroundTaskRegistration.AllTasks)
{
try
{
task.Value.Unregister(false);
}
catch
{
//
}
}
BackgroundTaskBuilder builder = new BackgroundTaskBuilder();
builder.Name = "Push Notifcation Task";
builder.TaskEntryPoint = typeof(PushNotification).FullName;
builder.SetTrigger(new PushNotificationTrigger());
builder.Register();
}
catch(Exception e)
{
if(e != null)
{
System.Diagnostics.Debug.WriteLine(e.HResult);
System.Diagnostics.Debug.WriteLine(e.InnerException);
}
}
}
Please don't forget to add this background task in Declarations section in Package.appmanifest file and name of Entry Point should match with builder.TaskEntryPoint = typeof(PushNotification).FullName; else you will get exception.
Hope it helps someone.
I need to browse a set of url adresses (yes another web scraper..).
I want to use tasks. But I have problem returning AFTER the browser is finished.
To be sure the site is fully loaded I have to jump to document_completed and from there I call the Navigate method with another url.
Something like this:
private WebBrowser browser;
private List<string> urlsToVisit;
int urlCounter = 0;
public PageBrowser(List<string> urls) //constructor
{
urlCounter = 0;
urlsToVisit = urls;
browser = new WebBrowser(); //one instance of browser for all urls
browser.ScriptErrorsSuppressed = true;
browser.DocumentCompleted += browser_DocumentCompleted;
}
//this I want to call from somewhere else and return true AFTER it opens all sites
public bool Run()
{
VisitPages();
return true;
}
private void VisitPages()
{
if (urlCounter < urlsToVisit.Count)
{
browser.Navigate(urlsToVisit[urlCounter]);
urlCounter++;
}
else
{
browser.Dispose();
}
}
private void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (e.Url.AbsolutePath != (sender as WebBrowser).Url.AbsolutePath) return;
System.Threading.Thread.Sleep(3000); //random interval between requests
VisitPages();
}
I am pretty sure, the solution is very simple but I just don't see it..
Thank you
Petr
I would suggest you to use a WebClient instead of a WebBrowser UI component since you don't seem to need to render anything. It seems as you just want to send requests to your list of urls and return true if everything went well, and return false if any type of problem occured.
private async Task<bool> VisitUrls()
{
var urls = new List<string>
{
"http://stackoverflow.com",
"http://serverfault.com/",
"http://superuser.com/"
};
var success = await BrowseUrls(urls);
return success;
}
private async Task<bool> BrowseUrls(IEnumerable<string> urls)
{
var timeoutWebClient = new WebClient();
foreach (var url in urls)
{
try
{
var data = await timeoutWebClient.DownloadDataTaskAsync(url);
if (data.Length == 0) return false;
}
catch (Exception ex)
{
return false;
}
}
//Everything went well, returning true
return true;
}
i have application that using await to retrieving data from windows azure, and using it along with retrieving data from json, so first i get data from json for the first row of the list and next list is from windows azure
private RootObjectDetail _hereRestDetail= null;
public RootObjectDetail hereRestDetail
{
get { return _hereRestDetail; }
set { this.SetProperty(ref this._hereRestDetail, value); }
}
private ObservableCollection<AddressDetail> _hereRestAddressDetail = null;
public ObservableCollection<AddressDetail> hereRestAddressDetail
{
get { return _hereRestAddressDetail; }
set { this.SetProperty(ref this._hereRestAddressDetail, value); }
}
private async void UpdateTransportDetail()
{
try
{
isBusy = true;
isBusyMessage = "Loading web server data...";
addressItem = await addressTable
//.Where(placeId = hereRestDetail.placeId )
.ToCollectionAsync();
WebClient client = new WebClient();
client.DownloadStringCompleted += (s, e) =>
{
if (e.Error == null)
{
RootObjectDetail result = JsonConvert.DeserializeObject<RootObjectDetail>(e.Result);
hereRestDetail = result;
hereRestAddressDetail.Clear();
hereRestAddressDetail.Insert(0,result.location.address);
var oc = new ObservableCollection<AddressDetail>();
foreach (var item in addressItem)
hereRestAddressDetail.Add(item);
}
else
{
isFailed = Visibility.Visible;
isFailedMessage = "Can't get data from web server, please refresh and make sure your internet data connected";
}
isBusy = false;
};
client.DownloadStringAsync(new Uri(hrefText + transportDetailURL));
}
catch (Exception)
{
isFailed = Visibility.Visible;
isFailedMessage = "Something wrong happen, please refresh";
}
}
but sometimes i giving me error like failed to connect to database, so maybe anyone can give me some way to making this call more efficient?