CEF shutdown makes the application to wait for infinite time during App shutdown [closed] - wpf

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 days ago.
Improve this question
The WPF application is using CEF to render the Url provided, and the loading is proper. But during the shutdown time observed the CEF is locking on its shutdown and hosting process has to wait for infinite times.
Here is the memory dump:
The CEF dispatcher:
[Waiting on Thread 0x3FC8, double-click or press enter to switch to thread]    >   
ntdll.dll!NtWaitForSingleObject()    Unknown
     KERNELBASE.dll!WaitForSingleObjectEx()    Unknown
     libcef.dll!00007ffa51ec0bdb()    Unknown
     libcef.dll!00007ffa52b035ba()    Unknown
     libcef.dll!00007ffa52b02683()    Unknown
     libcef.dll!00007ffa52b024fe()    Unknown
     libcef.dll!00007ffa51db2d07()    Unknown
     libcef.dll!00007ffa51db2bfe()    Unknown
     [Managed to Native Transition]    
     CefSharp.Core.Runtime.dll!CefSharp.Core.Cef.Shutdown()    Unknown
     CefSharp.Wpf.dll!CefSharp.Wpf.ChromiumWebBrowser.CefShutdown()    Unknown
     CefSharp.Wpf.dll!CefSharp.Wpf.ChromiumWebBrowser.DispatcherShutdownFinished(object sender, System.EventArgs e)    Unknown
The issue is not reproducible all the time, but it is happening in some remote machines there I don't have access. If anyone faced the same issue, please share your valuable suggestions.
Version used - 104.4.24+gdf482f6+chromium-104.0.5112.102
Below is the code used for the loading and shutdown purpose.
var settings = new CefSettings();
settings.IgnoreCertificateErrors = true;
settings.LogSeverity = LogSeverity.Disable;
settings.CefCommandLineArgs.Add("disable-gpu");
settings.CefCommandLineArgs.Add("disable-gpu-compositing");
settings.CefCommandLineArgs.Add("no-proxy-server", "1");
CefSharpSettings.SubprocessExitIfParentProcessClosed = true;
Cef.EnableWaitForBrowsersToClose();
CefSharpSettings.ShutdownOnExit = false;
private void Dispatcher_ShutdownFinished(object sender, EventArgs e)
{
Dispatcher.ShutdownFinished -= Dispatcher_ShutdownFinished;
Cef.Shutdown();
}
private void Dispatcher_ShutdownStarted(object sender, EventArgs e)
{
Dispatcher.ShutdownStarted -= Dispatcher_ShutdownStarted;
IsBrowserInitialized = false;
Cef.PreShutdown();
Cef.WaitForBrowsersToClose();
}
private void OnVisibilityChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
Dispatcher.BeginInvoke(new Action(() = >
{
var vm = DataContext as ViewModel;
if ((vm != null) && (vm.Visibility == Visibility.Visible))
{
Window.Visibility = Visibility.Visible;
LoadNewUrl();
Window.Activate();
}
else
{
ChromeBrowser ? .Load("about:blank");
}
}));
}
The Debug.log says,
[0217/180829.375:ERROR:angle_platform_impl.cc(43)] Display.cpp:992 (initialize): ANGLE Display::initialize error 0: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ..\..\third_party\angle\src\libANGLE\renderer\vulkan\RendererVk.cpp, initialize:1317.
[0217/180829.377:ERROR:gl_surface_egl.cc(831)] EGL Driver message (Critical) eglInitialize: Internal Vulkan error (-3): Initialization of an object could not be completed for implementation-specific reasons, in ..\..\third_party\angle\src\libANGLE\renderer\vulkan\RendererVk.cpp, initialize:1317.
[0217/180829.378:ERROR:gl_surface_egl.cc(1353)] eglInitialize SwANGLE failed with error EGL_NOT_INITIALIZED
[0217/180829.382:ERROR:gl_initializer_win.cc(134)] GLSurfaceEGL::InitializeOneOff failed.
[0217/180829.387:ERROR:viz_main_impl.cc(186)] Exiting GPU process due to errors during initialization
[0217/180834.568:ERROR:gpu_init.cc(486)] Passthrough is not supported, GL is disabled, ANGLE is

Related

Error CS0103: The name 'ZipFile' does not exist in the current context

i was working on .net core wpf game lancher but the error "Error CS0103: The name 'ZipFile' does not exist in the current context" appeared. even i used the following line: using System.IO.Compression; but it didnt work.
private void DownloadGameCompletedCallback(object sender, AsyncCompletedEventArgs e)
{
try
{
string onlineVersion = ((Version)e.UserState).ToString();
ZipFile.ExtractToDirectory(gameZip, rootPath, true); // error cs0103
File.Delete(gameZip);
File.WriteAllText(versionFile, onlineVersion);
VersionText.Text = onlineVersion;
Status = LauncherStatus.ready;
}
catch (Exception ex)
{
Status = LauncherStatus.failed;
MessageBox.Show($"Error finishing download: {ex}");
}
}
tried change namespace, class to GameLauncher in mainwindow.xaml (didn't work)

How to use process using Threads without stoping a timer in WPF? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed last year.
Improve this question
This is a little guide to help resolve a problem with timers that stops when opening a file using process to open it with the default application.
If you are using a timer in C# WPF you will notice that the timer will stop working until the file has been closed which may not be the behavior that you want.
Let say for instance that you want a timer to start as soon as the file you want to show to the user is open. While the user sees or read the file you want the timer to continue. Without using a Thread the timer will not continue it's work up until the file is closed.
This is the problem encountered:
I have a timer that is started by pressing a button (btnTache1) but it stops when I'm using System.Diagnostics.Process to open a file with it's default application using another button (btnVideo1). It only resume after the file is closed.
This a brief description of the components of the program:
There is a button to show the media called btnVideo1
The onclick event of the button defines a timer _timer1 and the file to show to the user _media1 and a countdown used by the timer _startingTimer1 set to 30 seconds.
Here is the code:
private int _startingTimer1;
private string _media1;
DispatcherTimer _timer1 = new DispatcherTimer();
private void btnVideo1_Click(object sender, RoutedEventArgs e)
{
_startingTimer1 = 30; // 30 seconds
// stop timer if already started
if (_timer1.IsEnabled == true)
{
_timer1.Stop();
}
// configure timer
_timer1 = new DispatcherTimer();
_timer1.Interval = TimeSpan.FromSeconds(1);
_timer1.Tick += timer_Tick1;
_timer1.Start();
// defining the file to show to the user
string procedure = "procedure1.mp4"
_media1 = "//10.10.0.1/Procedures/ + procedure;
ShowVideo(_media1);
}
// Action done when a tick for timer occur
private void timer_Tick1(object sender, EventArgs e)
{
// decreasing countdown
_startingTimer1--;
// calculate and show the timer (countdown)
TimeSpan time = TimeSpan.FromSeconds(_startingTimer1);
tbxTemps1.Text = time.ToString();
// if timer under 0
if (_startingTimer1 < 0)
{
// change background color depending on number
if (_startingTimer1 % 2 == 0)
btnTemps1.Background = new SolidColorBrush(Colors.OrangeRed);
else
btnTemps1.Background = new SolidColorBrush(Colors.LightGray);
}
}
// show the file to the user
private void ShowVideo(string media)
{
try
{
// define a process to show the file
System.Diagnostics.Process process = new System.Diagnostics.Process();
// declare the path to the file
process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
process.StartInfo.UseShellExecute = true;
// start the process to show the file to the user
process.Start();
process.WaitForExit();
}
catch
{
MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
To resolve the issue the use of a Thread really comes handy. Calling the function using a thread makes the timer continue in the primary thread while other things are done in parallel in another thread. To achieve this here's what I have changed.
I changed the ShowVideo method as follow:
private void ShowVideo(string media)
{
try
{
System.Diagnostics.Process process = new System.Diagnostics.Process();
process.StartInfo.FileName = new Uri(media, UriKind.Absolute).ToString();
process.StartInfo.UseShellExecute = true;
Thread showFile = new Thread(() => process.Start());
showFile.Start(); // start the Thread
showFile.Join();
showFile.WaitForExit();
}
catch
{
MessageBox.Show("Could not open the file.", "Error", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}

.NET 5.0 - Stop immediately a running thread in WPF application

I'm developing a WPF application for real-time data gathering from a remote client. Data acquisition is managed by a different thread (different from the one used to run the main application). When the users press the connection button, the data acquisition thread is launched and, simmetrically, when the disconnection button is pressed the thread should stop. Data reading stops only when the user decides it.
I use the following code:
private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
connectionThread = new Thread(new ThreadStart(myThreadStartFunc));
connectionThread.Start();
}
private void myThreadStartFunc()
{
TcpConnect();
ReadData();
}
private void TcpConnect()
{
mySocket = new Socket(...);
mySocket.Connect(ipEndPoint);
}
private void ReadData()
{
while(mySocket.Connected)
{
Thread.Sleep(300);
mySocket.Receive(data, ...);
}
}
private void DisconnectButton_Click(object sender, RoutedEventArgs e)
{
StopThread(connectionThread);
}
private void StopThread(Thread thread)
{
}
What should be the body of the StopThread method? Currently I'm using thread.Interrupt() in a try and catch structure in thte StopThread method. It generates an exception in the while loop of the data reading method, at line Thread.Sleep(300): System.Threading.ThreadInterrupted
Exception: Thread was interrupted from a waiting state.
I would like to use the thread.Abort() method, but it is obsolete (https://learn.microsoft.com/en-us/dotnet/core/compatibility/core-libraries/5.0/thread-abort-obsolete). Any suggestion? Thank you in advance.

Got null reference exception in Loaded event, where the count of SelectedItems in a child datagrid is accessed

Here is the top of the exception stack:
System.NullReferenceException: Object reference not set to an instance of an object.
at xx.TblQcLotListSelectionChanged(Object sender, SelectionChangedEventArgs e) in ...\InternalEventHandlerQCPage.cs:line 441
at xx.QCLotListPageLeftLoaded(Object sender, RoutedEventArgs e) in ...\InternalEventHandlerQCPage.cs:line 435
And this is the mentioned part of the InternalEventHandlerQCPage.cs:
private void QCLotListPageLeftLoaded(object sender, RoutedEventArgs e)
{
this.QCPage.QCShowRangesTblHitTest = true;
this.QCPage.QCShowRangesTblEnabled = true;
this.QCPage.LOTListRightTxtNameEnabled = false;
this.QCPage.LOTListFieldEnabled = false;
this.QCPage.LOTListNumberDateEnabled = false;
TblQcLotListSelectionChanged(null, null); //line 435
}
private void TblQcLotListSelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (this._QCLotListPageLeftXAML.tblLotList.SelectedItems.Count == 0) //line 441
{
this.QCPage.LOTListRightBtnUpEnabled = false;
this.QCPage.LOTListRightBtnDownEnabled = false;
this.QCPage.QCShowRangesBtnUpEnabled = false;
this.QCPage.QCShowRangesBtnDownEnabled = false;
...
"this" is a UserControl.
_QCLotListPageLeftXAML is also a UserControl used on a page inside a TabControl
tblLotList is a WPF DataGrid
QCPage is a dependency object containing only dependency properties for bindings
We got this exception when the datagrid had 300 items, which is the allowed maximum that we set. The datagrid has 4 columns, so it's not that heavy... Also the software has been running for a while before, so this hasn't occured on the sw start.
Do you have any idea what can go wrong here? SelectedItems can be null for a DataGrid?
Try, if the error occurs still, when you do this:
if (this._QCLotListPageLeftXAML.tblLotList.SelectedItems != null &&
this._QCLotListPageLeftXAML.tblLotList.SelectedItems.Count == 0)
{
}
Problem solved. It was another case when a released, compiled application complained for an other line in the stack than the line which actually caused the exception.

Update GUI using BackgroundWorker

I've been searching and found that a good way to perform background work and update the GUI is using background workers. However, doing this (stupid) little task (counting from 1 to 10000) it doesn't update the label content but prints to the debug! (This is just a spike solution for another project of course...)
Here's the code:
public partial class MainWindow : Window
{
BackgroundWorker bw = new BackgroundWorker();
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
bw.WorkerReportsProgress = true;
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.RunWorkerAsync();
}
void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("DONE");
}
void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Content = "going here: "+e.ProgressPercentage;
Debug.WriteLine(e.ProgressPercentage);
}
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i=0; i < 10000; i++)
{
bw.ReportProgress((i*100)/10000);
}
}
}
The ProgressChanged event is raised on the UI thread, not the worker thread. In your code, the worker thread is doing almost nothing (just loop from 0 to 10000 and call ReportProgress), most of the work is done on the UI thread. Basically, you're sending too many progress notifications. Because of this, the UI thread is almost always busy and has no time to render the new content of the label.
Rendering in WPF is not performed immediately when you change a property of a control, it is done on a separate dispatcher frame, which is processed when the dispatcher has nothing more urgent to do, based on the priority of the task. The priority used for rendering has a value of 7 (DispatcherPriority.Render); the ProgressChanged event is marshalled to the UI thread with a priority of 9 (DispatcherPriority.Normal), as specified on MSDN. So the ProgressChanged notifications always have a higher priority than rendering, and since they keep coming, the dispatcher never has time to process the rendering tasks.
If you just decrease the frequency of the notifications, your app should work fine (currently you're sending 100 notifications for each percentage value, which is useless):
void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10000; i++)
{
if (i % 100 == 0)
bw.ReportProgress(i / 100);
}
}
this.Dispatcher.BeginInvoke( (Action) delegate(){
label1.Content = "going here: "+e.ProgressPercentage;
});
Try to change the label using womething like this:
string Text = "going here: " + e.ProgressPercentage;
this.Invoke((MethodInvoker)delegate {
label1.Content = newText;
});
Note that i'm not sure it will work. I can not test it now. If it does not work, let me know and I will delete the answer.
If you need the a canonical way to do exactly what you want, look at the Hath answer in this post: How do I update the GUI from another thread?

Resources