2

I'm trying to run this code:

GetRepsButton.Command = new Command(async () =>
            {
                var url = @"https://url";

                HttpClient client = new HttpClient();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                //crashes here
                var test = await client.GetStringAsync(url);
            });

And when I do, the entire app crashes and the output window shows this error:

ROR: +[MSWrapperLogger MSWrapperLog:tag:level:]/7 Unhandled Exception:
UIKit.UIKitThreadAccessException: UIKit Consistency error: you are calling a UIKit method that can only be invoked from the UI thread.
  at UIKit.UIApplication.EnsureUIThread () [0x00020] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.6.0.16/src/Xamarin.iOS/UIKit/UIApplication.cs:89 
  at UIKit.UIGestureRecognizer.RemoveTarget (Foundation.NSObject target, System.IntPtr action) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.6.0.16/src/Xamarin.iOS/UIKit/UIGestureRecognizer.g.cs:342 
  at UIKit.UIGestureRecognizer.OnDispose () [0x00016] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.6.0.16/src/Xamarin.iOS/UIKit/UIGestureRecognizer.cs:41 
  at UIKit.UIGestureRecognizer.Dispose (System.Boolean disposing) [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.6.0.16/src/Xamarin.iOS/UIKit/UIGestureRecognizer.g.cs:959 
  at
 Foundation.NSObject.Finalize () [0x00000] in /Library/Frameworks/Xamarin.iOS.framework/Versions/12.6.0.16/src/Xamarin.iOS/Foundation/NSObject2.cs:143 
Resolved pending breakpoint at 'SelectRep.xaml.cs:110,1' to void NameSpace.<ClientPicker_SelectedIndexChanged1>d__3.MoveNext () [0x0000c].

Although I dont think I should have to since i'm not doing anything with the UI, I have tried InvokeOnMainThread which does not work. I've also tried changing to .Result instead of await, and I've tried GetAsync and reading the content, along with using WebClient instead of HttpClient. All cause this same error.

Any ideas? I'm using Xamarin forms 4 pre 7.

Kyle
  • 32,731
  • 39
  • 134
  • 184
  • can you provide more context around that line of code? The stacktrace looks like it is coming from a gesture recognizer, is that correct? – Jason Mar 29 '19 at 18:59
  • @Jason I haven't made any gesture recognizers in the project at all. I think that is internal code to xamarin.ios. If I comment out this one .getstringaync line, the app runs fine. – Kyle Mar 29 '19 at 19:01
  • I would "assume" this awaited call is within a `void` return method somewhere and thus causes the chained failure within some UI code (yours or the Forms4 preview code, would not be able to tell without more context of how/where you are using/calling that httpclient async method. – SushiHangover Mar 29 '19 at 19:09
  • @SushiHangover the code was inside a `Clicked` Event(`private async void ClientPicker_SelectedIndexChanged1(object sender, EventArgs e)`) on a `Button`, which the only choice is `void` as far as I understand? However I changed it to set the Command with an async command and still have the same problem. I updated my question to show the full code block. Am I misunderstanding how to go about async calls on button clicks? – Kyle Mar 29 '19 at 19:28
  • @SushiHangover this also happens if I use `WebClient.DownloadString()` which isn't async at all. – Kyle Mar 29 '19 at 19:35
  • @Kyle No, you have it right (void-based event handlers are unavoidable...). Are you removing that event handler anywhere? Something is causing the "strange" crash. Wondering when you say `ClientPicker_SelectedIndexChanged1` is on a button, is it a button, a picker? ?? – SushiHangover Mar 29 '19 at 19:36
  • I'm not removing the event anywhere, and it's on a Button. Sorry I know it has Picker in the name which is confusing. The code was originally running whenever a picker changed and using the picker values, but I've been trying to narrow down the code so I put it on a button and hard coded values to get the code as minimal as possible. – Kyle Mar 29 '19 at 19:42
  • After 8 hours of trying to get this to work, I switched to Visual Studio 2017 instead of the 2019 preview and it works fine. I assume this is a bug with the version of xamrarin.ios or mono that ships with the 2019 preview I guess.... – Kyle Mar 29 '19 at 23:05

1 Answers1

5

Use Device.BeginInvokeOnMainThread

Device.BeginInvokeOnMainThread(() =>
{
  //your code
});

https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.device.begininvokeonmainthread?view=xamarin-forms

Amir Touitou
  • 3,141
  • 1
  • 35
  • 31