Stuck in IMobileServiceTable.ToListAsync() - c#

I have modified the Xamarin/Azure TODO example. But the code is stuck in
IMobileServiceTable.ToListAsync()
This is my IO class:
class DataIO
{
BackgroundWorker DatabaseWorker = new BackgroundWorker();
IMobileServiceTable<UserPosition> PositionTable;
MobileServiceClient client;
public DataIO()
{
Init();
}
public void Init()
{
client = new MobileServiceClient(Constants.ApplicationURL);
PositionTable = client.GetTable<UserPosition>();
}
async void AddEntry(UserPosition entry)
{
await PositionTable.InsertAsync(entry);
}
public async Task<List<UserPosition>> GetEntries()
{
List<UserPosition> Entries = await PositionTable.ToListAsync();
return Entries;
}
public async void DeleteEntry(UserPosition entry)
{
await PositionTable.DeleteAsync(entry);
}
public async void AddToDatabase(UserPosition item)
{
await PositionTable.InsertAsync(item);
}
}
The debugger dosen't neither step over it nor throws an error.
How to handle that?
In an earlier call, there wasn't any problem.
EDIT:
I've rewritten the GetEntries() method to:
public async Task<List<UserPosition>> GetEntries()
{
Task<List<UserPosition>> task = PositionTable.ToListAsync();
List<UserPosition> entries = await task;
return entries;
}
according to this example. But the debugger just stays in the line
Task<List<UserPosition>> task = PositionTable.ToListAsync();

AFAIK, IMobileServiceTable.ToListAsync() would send the request as follows for retrieving the result:
Get https://<your-app-name>.azurewebsites.net/tables/UserPosition
I would recommend you using Fiddler to collect the network traces when calling IMobileServiceTable.ToListAsync(). Also, you could access the table endpoint from your mobile app via the browser to make sure your mobile app could work as expected. Additionally, here is a great tutorial about Handling Data in Mobile Clients, you could refer to it.

Related

How to access a Realm instance in the same thread that it was created in .NET (Xamarin-UWP)?

I am working on the migration from SQLite/WebApis to Realms in an App in Xamarin Forms.
This application manages a messaging service (Chat through SignalR).
The problem that has arisen is when a message is received, which I try to store in a database, the application crashes unexpectedly. (Question that did not happen with SQLite).
I am getting the famous error: realm accessed from incorrect, exactly when the 3rd or 4th message is trying to insert, it has been a bit difficult to see the precise moment.
As I could read, both in questions right here on Stackoverflow, and on the Dot-Net Realm GitHub. the instance must be accessed in the same thread that it was created.
As they suggest, one way to achieve this is by using the correct SynchronizationContext through AsyncContext.Run Nito.AsyncEx by Stephen Cleary or Device.BeginInvokeOnMainThread.
I ask the question because unfortunately, I handle the subject of threads and tasks at a basic level, in what way do I have to approach the previous suggestions to my code? or what should I set correctly to access the thread in which it was created?
This is my code:
LobbyViewModel
public LobbyViewModel()
{
ChatService.OnReceivePrivateMessage += ChatService_OnReceivePrivateMessage;
}
private async void ChatService_OnReceivePrivateMessage(object sender, MessageEventArgs args)
{
await SendMessage(…);
}
private async Task SendMessage(…)
{
await UpdateMetaData(…);
}
public async Task UpdateMetaData(…)
{
await ManagerService.InsertMetaDataChatAsync(metaDataChat);
}
ManagerService
public async Task InsertMetaDataChatAsync (MetaDataChatModel MetaDataChatModel)
{
IMetaDataChatServices MetaDataChatServices = App.AppContainer.Resolve<IMetaDataChatServices>();
IResponse DataResult = (await MetaDataChatServices.Insert(MetaDataChatModel));
}
Repository
public async Task<IResponse> CreateAsync(MetaDataChatModel MetaDataChatModel)
{
MetaDataChatModel.Id = Guid.NewGuid().ToString();
MetaDataChatModel.Partition = _realmManager.projectPartition;
var MetaDataChatDto = MetaDataChatModel.ToDto();
var realmInstance = await _realmManager.GetInstanceAsync();
if (realmInstance == null)
return new Response(false, "Realm instance can't be null");
await realmInstance.WriteAsync(realm =>
{
realm.Add(MetaDataChatDto, false);
});
return new Response(true);
}
RealmManager
public RealmManager()
{
RealmApp = App.Create(appId);
//DataBase = Realms.Realm.GetInstance(syncConfig);
}
public Task<Realms.Realm> GetInstanceAsync()
{
return Realms.Realm.GetInstanceAsync(syncConfig);
}
public async Task RealmLogInAsync()
{
if (RealmApp.CurrentUser == null)
{
User user = await RealmApp.
LogInAsync(Credentials.EmailPassword("email", "password"));
if (user == null)
{
return;
}
}
projectPartition = $"project={RealmApp.CurrentUser.Id}";
syncConfig = new SyncConfiguration(projectPartition, RealmApp.CurrentUser);
}
public async Task RealmLogOutAsync()
{
if (RealmApp != null && RealmApp.CurrentUser!=null)
{
await RealmApp.CurrentUser?.LogOutAsync();
}
}

Program ends before async result is received

I am writing a program to interact with the Spotify API via a command line.
I have some code here to take a command, and then execute the relevant function to retrieve data from Spotify.
This code shows the problem, I have left out irrelevant code.
public class CommandHandler
{
public async void HandleCommands()
{
var spotifyCommand = GetCommand();
if (spotifyCommand == SpotifyCommand.Current)
{
WriteCurrentSong(await new PlayerController().GetCurrentlyPlayingAsync());
}
if (spotifyCommand == SpotifyCommand.NextTrack)
{
WriteCurrentSong(await new PlayerController().NextTrackAsync());
}
Console.ReadLine();
//end of program
}
}
public class PlayerController
{
public async Task<SpotifyCurrentlyPlaying> NextTrackAsync()
{
using (var httpClient = new HttpClient())
{
//removed code to set headers etc
//Skip Track
var response = await httpClient.PostAsync("https://api.spotify.com/v1/me/player/next", null);
if (response.StatusCode != HttpStatusCode.NoContent)
{
//code to handle this case, not important
}
return await GetCurrentlyPlayingAsync();
}
}
public async Task<SpotifyCurrentlyPlaying> GetCurrentlyPlayingAsync()
{
using (var httpClient = new HttpClient())
{
//removed code to set headers etc
var response = await httpClient.GetAsync("https://api.spotify.com/v1/me/player/currently-playing");
response.EnsureSuccessStatusCode();
return JsonSerializer.Deserialize<SpotifyCurrentlyPlaying>(await response.Content.ReadAsStringAsync());
}
}
}
The two if statements in HandleCommands() call into PlayerController and await the result of the method. For some reason if I use await PlayerController.MethodCall() the call is made, however, the result does not return before the program finishes executing.
Strangely, this is not an issue if I use PlayerController.MethodCall().Result.
Any help will be greatly appreciated, as I would really rather not use .Result. Thanks!
Signature of the HandleCommands is an issue
public async void HandleCommands()
{
// ...
}
You are not showing how this method is called, but I assume it is something like below:
var handler = new CommandHandler();
handler.HandleCommands();
Because of async void method doesn't return Task and caller can not "observe" it's completion.
So application finishes without waiting for task to complete.
To fix - change method signature to below and await for task to complete
public async Task HandleCommands()
{
// ...
}
var handler = new CommandHandler();
await handler.HandleCommands();

Observer pattern using gRPC - C#

Sorry, if this is a stupid question but I don't find any useful information in the internet.
Has anyone ever tried to implement the observer pattern in C# using gRPC as communication?
If yes, please show me the link.
Many thanks in advance and best regards.
I have implemented a client convenience class wrapper to turn server streaming calls into regular events for a project I am working. Not sure if this is what you are after. Here is a simple gRPC server that just publishes the time as a string once every second.
syntax = "proto3";
package SimpleTime;
service SimpleTimeService
{
rpc MonitorTime(EmptyRequest) returns (stream TimeResponse);
}
message EmptyRequest{}
message TimeResponse
{
string time = 1;
}
The server implementation, which just loops once a second returning the string representation of the current time until canceled, is as follows
public override async Task MonitorTime(EmptyRequest request, IServerStreamWriter<TimeResponse> responseStream, ServerCallContext context)
{
try
{
while (!context.CancellationToken.IsCancellationRequested)
{
var response = new TimeResponse
{
Time = DateTime.Now.ToString()
};
await responseStream.WriteAsync(response);
await Task.Delay(1000);
}
}
catch (Exception)
{
Console.WriteLine("Exception on Server");
}
}
For the client, I created a class that contains the gRPC client and exposes the results of the server streaming MonitorTime call as a plain ole .net event.
public class SimpleTimeEventClient
{
private SimpleTime.SimpleTimeService.SimpleTimeServiceClient mClient = null;
private CancellationTokenSource mCancellationTokenSource = null;
private Task mMonitorTask = null;
public event EventHandler<string> OnTimeReceived;
public SimpleTimeEventClient()
{
Channel channel = new Channel("127.0.0.1:50051", ChannelCredentials.Insecure);
mClient = new SimpleTime.SimpleTimeService.SimpleTimeServiceClient(channel);
}
public void Startup()
{
mCancellationTokenSource = new CancellationTokenSource();
mMonitorTask = Task.Run(() => MonitorTimeServer(mCancellationTokenSource.Token));
}
public void Shutdown()
{
mCancellationTokenSource.Cancel();
mMonitorTask.Wait(10000);
}
private async Task MonitorTimeServer(CancellationToken token)
{
try
{
using (var call = mClient.MonitorTime(new SimpleTime.EmptyRequest()))
{
while(await call.ResponseStream.MoveNext(token))
{
var timeResult = call.ResponseStream.Current;
OnTimeReceived?.Invoke(this, timeResult.Time);
}
}
}
catch(Exception e)
{
Console.WriteLine($"Exception encountered in MonitorTimeServer:{e.Message}");
}
}
}
Now create the client and subscribe to the event.
static void Main(string[] args)
{
SimpleTimeEventClient client = new SimpleTimeEventClient();
client.OnTimeReceived += OnTimeReceivedEventHandler;
client.Startup();
Console.WriteLine("Press any key to exit");
Console.ReadKey();
client.Shutdown();
}
private static void OnTimeReceivedEventHandler(object sender, string e)
{
Console.WriteLine($"Time: {e}");
}
Which when run produces
I have left out a lot of error checking and such to make the example smaller. One thing I have done is for gRPC interfaces with many server streaming calls that may or may not be of interest to call clients, is to implement the event accessor (add,remove) to only call the server side streaming method if there is a client that has subscribed to the wrapped event. Hope this is helpful

SignalR hub Clients object disposed

I have the following SignalR Hub with in-memory connection management.
[Authorize]
public class ChatHub : Hub
{
private static readonly ConnectionMapping<string> _connections =
new ConnectionMapping<string>();
private readonly IMessageRepository _messagesRepository;
public ChatHub(IMessageRepository messageRepository)
{
_messagesRepository = messagesRepository;
}
public override async Task OnConnectedAsync()
{
var name = Context.User.Identity.Name;
_connections.Add(name, Context.ConnectionId);
//await Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnConnectedAsync();
}
public override async Task OnDisconnectedAsync(Exception exception)
{
var name = Context.User.Identity.Name;
_connections.Remove(name, Context.ConnectionId);
//await Groups.RemoveFromGroupAsync(Context.ConnectionId, "SignalR Users");
await base.OnDisconnectedAsync(exception);
}
public async void SendMessage(ChatMessage chatMessage)
{
var name = Context.User.Identity.Name;
var chatHistoryMessage = await _messagesRepository.SaveMessageAsync(chatMessage);
var availableConnections = _connections.GetConnections(name);
if (availableConnections.Any())
{
foreach (var connectionId in availableConnections)
{
Clients.Client(connectionId).SendAsync("ReceiveMessage", chatHistoryMessage);
}
}
else
{
}
}
}
However, when executing the code the following line
Clients.Client(connectionId).SendAsync("ReceiveMessage", 1);
raises an object disposed error on Clients.
This issue started happening when I added the repository line:
var chatHistoryMessage = await _messagesRepository.SaveMessageAsync(chatMessage);
SaveMessageAsync method:
public async Task<ChatHistory> SaveMessageAsync (ChatMessage chatMessage)
{
using (var conn = new SqlConnection(ConnProvider.ConnectionString))
{
await conn.OpenAsync();
return (await conn.QueryAsync<ChatHistory>("[mob].[spSaveChatMessage]",
new
{
..
},
commandType: CommandType.StoredProcedure)).FirstOrDefault();
}
}
Why would my Clients object be disposed? If I wait with the debugger that issue never happens.
It looks like the SendMessage method should be an async Task rather than an async void.
The issue could be caused by the way the SignalR framework runs async voids.
See this article for a good overview.
Async methods returning void don’t provide an easy way to notify the
calling code that they’ve completed.

Waiting for Async calls to finish

I'm working with the Philips Hue, and I need to get some information from the hue bridge before I can populate my application. The requests are made via HTTP/JSON. I have no issue when I run all my code async, but when I try to break out my code so that I have a separate method to update the UI upon loading I'm getting a System.NullReferenceException on myLights. I'm assuming that's because my startUpProcedure() isn't finished yet, hence myLights has not been set. I can't seem to figure out how to wait for the startUpProcedure() to finish before I run setupUI().
To further back that up, if I just run startUpProcedure() without setupUI() I get no issues. And then if I run setupUI() from say a button click it runs just fine.
Clearly I'm missing something here. I just can't seem to find the answer.
So to succinctly put the question: How do I wait for these Async calls to finish so that I can use variables that are depended on their return values?
public sealed partial class MainPage : Page
{
public string appKey;
public string myIP;
public IEnumerable<Light> myLights;
public ILocalHueClient myClient;
public MainPage()
{
this.InitializeComponent();
startUpPocedure();
setupUI();
}
public async Task startUpPocedure()
{
await startUp();
await getLights();
}
public async Task startUp()
{
if (await findBridgeIP())
{
Debug.WriteLine("Bridge Found...");
//Do Actions
}
else
{
//Error!!
Debug.WriteLine("No hue found");
}
Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Windows.Storage.StorageFolder localFolder = Windows.Storage.ApplicationData.Current.LocalFolder;
try {
appKey = localSettings.Values["appKey"].ToString();
Debug.WriteLine("appKey loaded: " + appKey);
//Load up
myClient = new LocalHueClient(myIP);
myClient.Initialize(appKey);
}
catch {
Debug.WriteLine("Need to register app");
}
}
async Task getLights()
{
myLights = await myClient.GetLightsAsync();
Debug.WriteLine("Light Count " + myLights.Count());
IEnumerable<string> myLightNames;
List<string> myTempList = new List<string>();
foreach (Light l in myLights)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames = myTempList;
comboBox_LightSelect.ItemsSource = myLightNames;
}
private void setupUI()
{
//Populate the Combo Box
IEnumerable<string> myLightNames;
List<string> myTempList = new List<string>();
foreach (Light l in myLights)
{
myTempList.Add(l.Name);
Debug.WriteLine(l.Name);
}
myLightNames = myTempList;
comboBox_LightSelect.ItemsSource = myLightNames;
}
Your startUpPocedure method in MainPage constructor returns Task almost immediately, and because you're not awaiting it, code execution goes to the next line right after that and setupUI gets called. So when your code starts to enumerate myLights collection, it's still null because startUpPocedure and therefore getLights are still running.
Problem is, you can't await asynchronous methods in a constructor, so in your case solution will be to move both startUpPocedure and setupUI to single async method, await them inside this method and call it from constructor similar to this:
public MainPage()
{
this.InitializeComponent();
Startup();
}
private async void Startup()
{
await startUpPocedure();
setupUI();
}
You should leave only InitializeComponent in the constructor, and move all other logic to Loaded event handler,
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.frameworkelement.loaded
Then you can mark that handler as async, and use await in it to await on async methods.

Categories