My webview2 initialization doesn't work for some group of users, But for some it works properly. It throws an timeout exception for some users.
Below is my code-
public async Task InitializeAsync()
{
EnsureTemplate();
Browser.NavigationStarting += Browser_NavigationStarting;
Browser.NavigationCompleted += Browser_NavigationCompleted;
Browser.PreviewKeyDown += Browser_PreviewKeyDown;
Browser.CoreWebView2InitializationCompleted += Browser_CoreWebView2InitializationCompleted;
var cachePath = WebUIConfigSection.Current.AbsoluteCachePath;
var environment = await CoreWebView2Environment.CreateAsync(null, cachePath, null);
await Browser.EnsureCoreWebView2Async(environment);
}
Exception details-
Type: System.Runtime.InteropServices.COMException
Target site: Void ThrowExceptionForHRInternal(Int32, IntPtr)
Message: This operation returned because the timeout period expired. (HRESULT: 0x800705B4)
Source: mscorlib
Stacktrace:
vid System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo) vid Microsoft.Web.WebView2.Core.CoreWebView2Environment.d__54.MoveNext() vid System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() vid System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) vid Microsoft.Web.WebView2.Wpf.WebView2.<>c__DisplayClass27_0.<g__Init|0>d.MoveNext()
What I did to avoid the exception is to set a timer that does a .Stop() when the query exceeded a certain time (configurable).
You could use the same to determine how long it takes WebView to timeout.
I assume that the target page is not using frames.
Related
I have the following Code:
System.Threading.Tasks.Task appointmentEndTask = App.ArdaBusinessLogic.AppointmentEnd(_appointment);
System.Threading.Tasks.Task appointmentEndCompletedTask = appointmentEndTask.ContinueWith(
async task =>
{
_appointmentDetailPage.IsDirty = true;
await App.MasterNavigationPage.Navigation.PopModalAsync();
},
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskContinuationOptions.OnlyOnRanToCompletion,
System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());
System.Threading.Tasks.Task appointmentEndFaultedTask = appointmentEndTask.ContinueWith(
async task =>
{
await App.MasterNavigationPage.Navigation.PopModalAsync();
await App.ShowErrorPageAsync(task.Exception);
},
System.Threading.CancellationToken.None,
System.Threading.Tasks.TaskContinuationOptions.OnlyOnFaulted,
System.Threading.Tasks.TaskScheduler.FromCurrentSynchronizationContext());
So if the "AppointmentEnd"-Task completes the current Modal-Page should be closed. From time to time (not always!) i get the following error in my crash logs. Linenumber 139 is "await App.MasterNavigationPage.Navigation.PopModalAsync()" after "_appointmentDetailPage.IsDirty = true" in this case.
Xamarin caused by: android.runtime.JavaProxyThrowable:
System.AggregateException: A Task's exception(s) were not observed
either by Waiting on the Task or accessing its Exception property. As
a result, the unobserved exception was rethrown by the finalizer
thread. ---System.ArgumentOutOfRangeException: Index was out of
range. Must be non-negative and less than the size of the collection.
Parameter name: index at
System.Collections.Generic.List`1[T].get_Item (System.Int32 index)
[0x00009] in
/Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:180
at Xamarin.Forms.Application+NavigationImpl+<OnPopModal>d__2.MoveNext
() [0x00022] in D:\a\1\s\Xamarin.Forms.Core\Application.cs:381
--- End of stack trace from previous location where exception was thrown --- at
CPM.Arda.Mobile.Freelancer.Ui.Pages.Appointment.Complete+<<confirmButton_Clicked>b__5_0>d.MoveNext
() [0x0007d] in
D:\ProjekteTFVC\ArdaMobileFreelancer\SourceCode\Ui\1.0\Pages\Appointment\Complete.xaml.cs:139
--- End of inner exception stack trace ---
---(Inner Exception #0) System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the
collection. Parameter name: index at
System.Collections.Generic.List`1[T].get_Item (System.Int32 index)
[0x00009] in
/Users/builder/jenkins/workspace/xamarin-android-d15-9/xamarin-android/external/mono/external/corefx/src/Common/src/CoreLib/System/Collections/Generic/List.cs:180
at Xamarin.Forms.Application+NavigationImpl+<OnPopModal>d__2.MoveNext
() [0x00022] in D:\a\1\s\Xamarin.Forms.Core\Application.cs:381
--- End of stack trace from previous location where exception was thrown --- at
CPM.Arda.Mobile.Freelancer.Ui.Pages.Appointment.Complete+<<confirmButton_Clicked>b__5_0>d.MoveNext
() [0x0007d] in
D:\ProjekteTFVC\ArdaMobileFreelancer\SourceCode\Ui\1.0\Pages\Appointment\Complete.xaml.cs:139
Unfortunately, I do not understand how it can come to this error. Can you help me?
First, why are you using such a complicated syntax instead of taking advantage of async await?
public async void EndAppointement()
{
try
{
await App.ArdaBusinessLogic.AppointmentEnd(_appointment);
_appointmentDetailPage.IsDirty = true;
await App.MasterNavigationPage.Navigation.PopModalAsync();
}
catch (Exception exception)
{
await App.MasterNavigationPage.Navigation.PopModalAsync();
await App.ShowErrorPageAsync(exception);
}
}
Second, looking at XF source code:
protected override async Task<Page> OnPopModal(bool animated)
{
Page modal = ModalStack[ModalStack.Count - 1];
if (_owner.OnModalPopping(modal))
{
_owner.OnPopCanceled();
return null;
}
Page result = await base.OnPopModal(animated);
result.Parent = null;
_owner.OnModalPopped(result);
return result;
}
It seems that your modal stack is messed up: meaning you are trying to pop pages that are not on the stack. Are you sure you're on a modal page? Maybe use PopAsync instead of PopModalAsync.
I'm using Azure Service Bus Topics with the AMQP protocol in the West Europe datacenter.
This is a schematic way of how the solution implented works:
private Microsoft.Azure.ServiceBus.SubscriptionClient CreateClient() {
string serviceBusConnectionString;
strin serviceBusTopicName;
string subscriptionName;
var subscriptionClient = new Microsoft.Azure.ServiceBus.SubscriptionClient(serviceBusConnectionString, serviceBusTopicName, subscriptionName) {
PrefetchCount = 0
};
return subscriptionClient;
}
public async Task<ISubscriptionClient> CreateSubscriptionClientAsync() {
//Some logic on the subscriptionClient, caching, creating a new one if it doesn't exists, etc.
return CreateClient()
}
private async Task CallbackAsync(Message msg, CancellationToken cancellationToken) {
//Do stuff with the Message
//when you're done Completethe message
}
public async Task<string> OpenAsync(CancellationToken cancellationToken) {
subscriptionClient = await CreateSubscriptionClientAsync().ConfigureAwait(false);
var messageHandlerOptions = new MessageHandlerOptions(ExceptionReceivedHandlerAsync) {
AutoComplete = false,
MaxAutoRenewDuration = TimeSpan.FromHours(8)
};
subscriptionClient.RegisterMessageHandler(CallbackAsync, messageHandlerOptions);
return string.Empty;
}
But last night I had couple of thousand exception like this one:
Exception: "System.InvalidOperationException: The AMQP object g2b-sessionXXXXXXXX is closing. Operation 'attach' cannot be performed.
at Microsoft.Azure.ServiceBus.Core.MessageReceiver.<OnReceiveAsync>d__86.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.Azure.ServiceBus.Core.MessageReceiver.<>c__DisplayClass64_0.<<ReceiveAsync>b__0>d.MoveNext()
I'm using the Microsoft.Azure.ServiceBus v3.1.0.0,
On line I didn't find anything useful about this "Operation 'attach' cannot be performed".
On the message bus exception list page I didn't find any information about this specific problem. And in the status history site there is no reference about any outage involving Service Bus.
Did anyone experience this problem before?
What is causing the exception?
Do I need to implement any retry logic? How?
Any help is apreciated, thanks.
I'm stressing a service I'm writing that uses a WebSocket taken from AcceptWebSocketAsync. The code I'm using to send messages through the WebSocket is this:
static bool
SendMessage(WebSocket webSocket, WebSocketMessage message, byte[] buffer, CancellationToken cancellationToken)
{
try {
var endOfMessage = false;
do {
using(var timeout = new CancellationTokenSource(webSocketsTimeout))
using(var lcts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeout.Token)) {
var count = message.Content.Read(buffer, 0, buffer.Length);
endOfMessage = count < buffer.Length;
// ReSharper disable once MethodSupportsCancellation
webSocket
.SendAsync(new ArraySegment<byte>(buffer, 0, count), message.Type, endOfMessage, lcts.Token)
.Wait() // SendAsync should be canceled using the Token.
;
}
} while(endOfMessage == false);
return true;
}
catch(Exception e) {
TraceConnectionError(e);
return false;
}
finally {
message.Dispose();
}
}
My problem is that under "stress" (I'm opening and closing 6 connections every 30 seconds until the system fails), I'm getting:
Unhandled Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.Net.HttpListenerException: An operation was attempted on a nonexistent network connection
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.WriteAsyncFast(HttpListenerAsyncEventArgs eventArgs)
at System.Net.WebSockets.WebSocketHttpListenerDuplexStream.<MultipleWriteAsyncCore>d__38.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendFrameAsync>d__48.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task)
at System.Net.WebSockets.WebSocketBase.WebSocketOperation.<Process>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Net.WebSockets.WebSocketBase.<SendAsyncCore>d__47.MoveNext()
--- End of inner exception stack trace ---
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
Shouldn't the Wait() I'm using be enough to "observe" the Task exception?
The problem was a race condition in .NET framework code.
I've reported the bug here.
As a workaround, I keep a list of used WebSockets which I regularly check for State != Open and then call this code:
public static class WebSocketXs
{
readonly static Assembly assembly = typeof(WebSocket).Assembly;
readonly static FieldInfo m_InnerStream = assembly.GetType("System.Net.WebSockets.WebSocketBase").GetField(nameof(m_InnerStream), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo m_ReadTaskCompletionSource = assembly.GetType("System.Net.WebSockets.WebSocketHttpListenerDuplexStream").GetField(nameof(m_ReadTaskCompletionSource), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo m_WriteTaskCompletionSource = assembly.GetType("System.Net.WebSockets.WebSocketHttpListenerDuplexStream").GetField(nameof(m_WriteTaskCompletionSource), BindingFlags.NonPublic | BindingFlags.Instance);
readonly static FieldInfo[] completionSourceFields = {m_ReadTaskCompletionSource, m_WriteTaskCompletionSource };
/// <summary>
/// This fixes a race that happens when a <see cref="WebSocket"/> fails and aborts after failure.
/// The <see cref="completionSourceFields"/> have an Exception that is not observed as the <see cref="WebSocket.Abort()"/>
/// done to WebSocketBase <see cref="m_InnerStream"/> is just <see cref="TaskCompletionSource{TResult}.TrySetCanceled()"/> which
/// does nothing with the completion source <see cref="Task.Exception"/>.
/// That in turn raises a <see cref="TaskScheduler.UnobservedTaskException"/>.
/// </summary>
public static void
CleanUpAndDispose(this WebSocket ws)
{
foreach(var completionSourceField in completionSourceFields) {
m_InnerStream
.GetValue(ws)
.Maybe(completionSourceField.GetValue)
.Maybe(s => s as TaskCompletionSource<object>)?
.Task
.Exception
.Maybe(_ => {}) // We just need to observe any exception.
;
}
ws.Dispose();
}
}
I have a C# project with a service reference against a web service.
I have the following code, first to trigger a method at the service request:
private void Button_Click(object sender, RoutedEventArgs e)
{
App.service.getFileCompleted += service_getFileCompleted;
App.service.getFileAsync(App.user, App.document);
}
And the service_getFileCompleted is supposed to retrieve a byte[], put it into a file and then open that file with the default application:
async void service_getFileCompleted(object sender, BackendReference.getFileCompletedEventArgs e)
{
string tmp = "temp." + e.Result.type;
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
StorageFile localFile = await local.CreateFileAsync(tmp, CreationCollisionOption.ReplaceExisting);
using (Stream writeStream = await localFile.OpenStreamForWriteAsync())
{
writeStream.Seek(0, SeekOrigin.End);
await writeStream.WriteAsync(e.Result.fileData, 0, e.Result.fileData.Length);
}
await Windows.System.Launcher.LaunchFileAsync(localFile);
}
}
First time the apps starts, and the button is triggered it works like a charm. However, when pressing the button the second time the row
Stream writeStream = await localFile.OpenStreamForWriteAsync()
casts an System.UnauthorizedAccessException.
More exactly:
System.UnauthorizedAccessException: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.IO.WindowsRuntimeStorageExtensions.d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.IO.WindowsRuntimeStorageExtensions.d__5.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at archive.DocumentDetail.d__0.MoveNext()} System.Exception {System.UnauthorizedAccessException}
Why is this so?
Thanks
I am working with async operations with sockets (.Net 4 - VS 2010 SP1) and all seems to be working okay. However, after write and run an automated test, it pass green but displays an exception message:
---- UNHANDLED EXCEPTION ----
Thread Name: <No Name>
System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. ---> System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.EndAccept(IAsyncResult asyncResult)
at P2PNet.Listener.<ListenForConnections>b__0(IAsyncResult r) in C:\Users\lucas.ontivero\Documents\Visual Studio 2010\Projects\P2PNet\P2PNet\Listener.cs:line 76
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs)
--- End of inner exception stack trace ---
at System.Threading.Tasks.TaskExceptionHolder.Finalize()
---> (Inner Exception #0) System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'System.Net.Sockets.Socket'.
at System.Net.Sockets.Socket.EndAccept(IAsyncResult asyncResult)
at P2PNet.Listener.<ListenForConnections>b__0(IAsyncResult r) in C:\Users\lucas.ontivero\Documents\Visual Studio 2010\Projects\P2PNet\P2PNet\Listener.cs:line 76
at System.Threading.Tasks.TaskFactory`1.FromAsyncCoreLogic(IAsyncResult iar, Func`2 endMethod, TaskCompletionSource`1 tcs)<---
I know what that exception means, it means the socket was closed before the EndAccept method was called. I have no problems with that, what I really don´t know is how to prevent that exception in an elegant way. This is my code:
private void ListenForConnections()
{
try
{
Task.Factory.FromAsync<Socket>(_listener.BeginAccept, _listener.EndAccept, _listener)
.ContinueWith(task =>
{
if (task.IsFaulted) return;
ListenForConnections();
var newSocket = task.Result;
RaiseClientConnectedEvent(new ConnectionEventArgs(newSocket));
}, TaskContinuationOptions.OnlyOnRanToCompletion);
}
catch (ObjectDisposedException)
{
}
I´ve tried with the line:
if (task.IsFaulted) return;
and also with:
.ContinueWith(task=>{}, TaskContinuation.OnlyOnFault);
But the exception is thrown anyway. Which is the way to prevent the exception?
Thank you!
Your line:
if (task.IsFaulted) return;
Is returning not faulted because you are checking the continuation task's status, not the preceding task. Change it to this:
private void ListenForConnections() {
Task<Socket> listentask = Task.Factory.FromAsync<Socket>(_listener.BeginAccept, _listener.EndAccept, _listener);
listentask.ContinueWith(task => {
if (listentask.IsFaulted) {
//observe exception
Exception exception = listentask.Exception;
return;
}
ListenForConnections();
var newSocket = listentask.Result;
RaiseClientConnectedEvent(new ConnectionEventArgs(newSocket));
});
//don't forget to start it
listentask.Start();
}
You need to observe the exception by reading the Exception property. Do that inside of your continuation.