Animated GIF while database connects in WPF - sql-server

I am working on an application that connects to Database as soon as it opens. Sometimes, it takes about 10-15 seconds before the database file gets connected and until then, no controls are loaded, it just loads a blank window and the cursor shows working. I tried using this library to use an animated GIF but it is not loading it before trying DB connection. I am using SQL Server Express and connecting to an mdf file. I tried placing code to display the <image/> before the SqlConnection and SqlDataAdapter Objects but even that didn't help. Any suggestions would be appreciated. Thanks in advance.

Do all the loading processes on a different thread,
Best way to do this is to use a BackgroundWorker
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx
Initialize
bw.WorkerSupportsCancellation = true;
bw.WorkerReportsProgress = true;
bw.DoWork +=
new DoWorkEventHandler(bw_DoWork);
Usage
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
for (int i = 1; (i <= 10); i++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress((i * 10));
}
}
}

Related

Check connection to database in thread

how to check connection to database while login form is showing to user before show all tools on the login form ?
In an application, I plan to arrange the following steps:
1-Login form without any special tools except a label and background image (similar to a Splash form).
2. Behind the login form (preferably inside a thread) is the connection to the server, and the user see a label with this text: try to connect to database...
3. If a connection is established (flag == right), a series of tools will be displayed for login user.
4. If the connection to the server is not established (flag == false), a series of other tools will be displayed to user for addressing the server.
I hope I could clearly make it.
using System;
using System.Windows.Forms;
using Microsoft.Data.ConnectionUI;
using System.Reflection;
public partial class LoginForm : Form
{
public LoginForm()
{
this.DoubleBuffered = true;
InitializeComponent();
System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(CheckConnection));
t.Start();
System.Threading.Thread.Sleep(5000);
t.Abort();
}
bool flag;
private void CheckConnection()
{
using (System.Data.SqlClient.SqlConnection connection =
new System.Data.SqlClient.SqlConnection
(connectionString))
{
try
{
connection.Open();
connection.Close();
flag = true;
}
catch
{
flag = false;
}
}
}
private void SplashScreenForm_Load(object sender, EventArgs e)
{
if (flag)
{
//Do somethings to login user
}
else
{
//Do something to create connection to database
}
}
The problem with this code is that the thread starts running before the form is displayed, and the program initially starts with a delay and immediately all the tool is displayed. Thanks for giving friends guidance.
I used Backgroundworker controller to solve this problem. It works very excellent.
Refer to https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.backgroundworker?view=netframework-4.8

Accessing document elements when using Windows.Forms.WebBrowser

I'm new to automating webpage access, so forgive what is probably a remedial question. I'm using C#/Windows.Forms in a console app. I need to programmatically enter the value of an input on a webpage that I cannot modify and that is running javascript. I have successfully opened the page (triggering WebBrowser.DocumentCompleted). I set browser emulation mode to IE11 (in registry), so scripts run without errors. When DocumentCompleted() triggers, I am unable to access the document elements without first viewing the document content via MessageBox.Show(), which is clearly not acceptable for my unattended app.
What do I need to do so that my document elements are accessbile in an unattended session (so I can remove MessageBox.Show() from the code below)? Details below. Thank you.
The input HTML is:
<input class="input-class" on-keyup="handleKeyPress($key)" type="password">
My DocumentCompleted event handler is:
private static void LoginPageCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = ((WebBrowser)sender);
var document = wb.Document;
// I'm trying to eliminate these 3 lines
var documentAsIHtmlDocument = (mshtml.IHTMLDocument)document.DomDocument;
var content = documentAsIHtmlDocument.documentElement.innerHTML;
MessageBox.Show(content);
String classname = null;
foreach (HtmlElement input in document.GetElementsByTagName("input"))
{
classname = input.GetAttribute("className");
if (classname == "input-class")
{
input.SetAttribute("value", password);
break;
}
}
}
The problem for me was that the page I'm accessing is being created by javascript. Even though documentComplete event was firing, the page was still not completely rendered. I have successfully processed the first page by waiting for the document elements to be available and if not available, doing Application.DoEvents(); in a loop until they are, so I know now that I'm on the right track.
This SO Question helped me: c# WebBrowser- How can I wait for javascript to finish running that runs when the document has finished loading?
Note that checking for DocumentComplete does not accurately indicate the availability of the document elements on a page generated by javascript. I needed to keep checking for the elements and running Application.DoEvents() until they became available (after the javascript generated them).
If the problem comes from the creation of a STAThread, necessary to instantiate the underlying Activex component of WebBrowser control, this is
a modified version of Hans Passant's code as shown in the SO Question you linked.
Tested in a Console project.
class Program
{
static void Main(string[] args)
{
NavigateURI(new Uri("[SomeUri]", UriKind.Absolute), "SomePassword");
Console.ReadLine();
}
private static string SomePassword = "SomePassword";
private static void NavigateURI(Uri url)
{
Thread thread = new Thread(() => {
WebBrowser browser = new WebBrowser();
browser.DocumentCompleted += browser_DocumentCompleted;
browser.Navigate(url);
Application.Run();
});
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
}
protected static void browser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser browser = ((WebBrowser)sender);
if (browser.Url == e.Url)
{
while (browser.ReadyState != WebBrowserReadyState.Complete)
{ Application.DoEvents(); }
HtmlDocument Doc = browser.Document;
if (Doc != null)
{
foreach (HtmlElement input in Doc.GetElementsByTagName("input"))
{
if (input.GetAttribute("type") == "password")
{
input.InnerText = SomePassword;
//Or
//input.SetAttribute("value", SomePassword);
break;
}
}
}
Application.ExitThread();
}
}
}

Open New Windows from Background Thread on ViewModel

So I have a WPF application (MVVM) with a Splash Screen. On the splash screen startup I have a background thread on the ViewModel that does some start up related activities. In certain instances I want to open a couple of additional windows (user input needed etc...). I was getting a number of issues/errors/exceptions while trying to do this (mostly around that new window - also MVVM - trying to populate its UI items, such as combo boxes). So I've pulled back the issue to a simpler form - the "tempWindow" doesn't have anything so it doesn't throw UI population errors, but basically it does just open them and once the background thread is done, closes them all. If someone could point me in the right direction on what I am doing incorrectly here it would be appreciated.
The constructor for the ViewModel kicks off a background thread
public SplashScreenViewModel()
{
this.LoadingStatusText = "Starting Startup Processing ... ";
this.VersionNumber = "version " + System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
var threadBackgroundStartUpProcesses = new Thread(new ThreadStart(this.BackgroundStartUpProcesses));
threadBackgroundStartUpProcesses.SetApartmentState(ApartmentState.STA);
threadBackgroundStartUpProcesses.IsBackground = true;
threadBackgroundStartUpProcesses.Start();
}
The background thread, should just open three windows (which it does) but those windows should stay open (they disappear once the thread completes).
private void BackgroundStartUpProcesses()
{
for (int i = 0; i < 3; i++)
{
var objTempWindow = new tempWindow();
objTempWindow.Show();
}
}
// EDIT: updated with responses, now get an error when the TempWindow has a comboBox that is being populated from the TempWindowViewModel.
private void BackgroundStartUpProcesses()
{
for (int i = 0; i < 3; i++)
{
var objTempWindow = new tempWindow();
objTempWindow.Show();
}
System.Windows.Threading.Dispatcher.Run();
}
When it goes to open the TempWindow the exception: "The calling thread cannot access this object because a different thread owns it." is thrown and appears to be when a ComboBox on that Window is trying to be populated.
I suspect that windows need an owner and when the owner dies, so does the window. Opening the windows on the main thread makes them stick around. Something like this...
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
var threadBackgroundStartUpProcesses = new Thread(new ParameterizedThreadStart(this.BackgroundStartUpProcesses));
threadBackgroundStartUpProcesses.SetApartmentState(ApartmentState.STA);
threadBackgroundStartUpProcesses.IsBackground = true;
threadBackgroundStartUpProcesses.Start(System.Windows.Threading.Dispatcher.CurrentDispatcher);
}
private void BackgroundStartUpProcesses(object d)
{
System.Windows.Threading.Dispatcher dispatcher = (System.Windows.Threading.Dispatcher) d;
for (int i = 0; i < 3; i++)
{
dispatcher.BeginInvoke((Action)(() =>
{
var objTempWindow = new tempWindow();
objTempWindow.Show();
}));
}
}
}
edit
I've just done some digging on WPF threading and it looks like you can open windows on multiple threads, but you need to start the new dispatcher. See near the end of this page:
http://msdn.microsoft.com/en-us/library/ms741870.aspx
In your BackgroundStartupProcesses, under objTempWindow.Show() add this line
System.Windows.Threading.Dispatcher.Run();
Are you setting your MainWindow before closing the splash screen? WPF sets the first opened window of an application as the MainWindow and unless you've changed the ShutdownMode of your App.xaml then once you close the splash screen the application shuts down.

Progress Bar for unknown process time

I am developing winform(c#) that start/stop/restart windows services. I want to put a progress bar till the action is completed. I am new to .net programming. Kindly help me on to achieve this.
You cannot show meaningful progress when you don't know how long it takes. You can't know, services take anywhere from 1 to 30 seconds to start. All you can do is show a "I'm not dead, working on it" indicator to the user. ProgressBar supports that, set the Style property to "Marquee".
You'll also need to start the service in a worker thread to avoid your UI from freezing. That's best done with a BackgroundWorker. Make it look similar to this:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
ServiceProgressBar.Style = ProgressBarStyle.Marquee;
ServiceProgressBar.Visible = false;
}
private void StartButton_Click(object sender, EventArgs e) {
this.StartButton.Enabled = false;
this.ServiceProgressBar.Visible = true;
this.backgroundWorker1.RunWorkerAsync("foo");
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
var ctl = new ServiceController((string)e.Argument);
ctl.Start();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
this.StartButton.Enabled = true;
this.ServiceProgressBar.Visible = false;
if (e.Error != null) {
MessageBox.Show(e.Error.ToString(), "Could not start service");
}
}
You must divide up the start/stop/restart progress in small parts and after the part is finished you set the progress bar.
For an instant update you need to get into the methods you are executing to get feedback about its status.
Do you mean that you want to start/restart/stop more than one service and want the progress bar to indicate "how far you've processed the list of services to be started/restarted/stopped"? You could do something like:
progressBar.Maximum = listOfServicesToStart.Count;
progressBar.Value = 0;
for (int i = 0; i < listOfServicesToStart.Count; i++)
{
// Start service listOfServicesToStart[i]
progressBar.Value = i;
Application.DoEvents();
}
If you are planning to visualize the starting process of a service: I guess you can't do it nicely. What the Services snap-in in Windows seems to do is:
It tries to start/restart/stop the service
It calls ServiceController.WaitForStatus with a 1sec timeout to see whether the service has entered the respective state
Increases the progress bar value by one and goes to 2. until a timeout is detected (you need to find a reasonable number of seconds to wait for the service to enter the desired state)
This seems to be the only way.

Images not downloading on second load in WPF

I have a WPF application which has a UserControl called MyBook that, on Loaded will fire a background thread to get a list of Domain Objects each with a URL to an Azure Image hosted in blob storage.
For each domain object I get back, I add a new instance of a custom control called LazyImageControl which will download the image from Azure in the background and render the image when its done.
This works just fine, but when I add a second MyBook control to the scene the images dont load for some reason, I cannot figure out why this is.
Here is the code for the LazyImageControl
public LazyImageControl()
{
InitializeComponent();
DataContextChanged += ContextHasChanged;
}
private void ContextHasChanged(object sender, DependencyPropertyChangedEventArgs e)
{
// Start a thread to download the bitmap...
_uiThreadDispatcher = Dispatcher.CurrentDispatcher;
new Thread(WorkerThread).Start(DataContext);
}
private void WorkerThread(object arg)
{
var imageUrlString = arg as string;
string url = imageUrlString;
var uriSource = new Uri(url);
BitmapImage bi;
if (uriSource.IsFile)
{
bi = new BitmapImage(uriSource);
bi.Freeze();
_uiThreadDispatcher.Invoke(DispatcherPriority.Send, new DispatcherOperationCallback(SetBitmap), bi);
}
else
{
bi = new BitmapImage();
// Start downloading the bitmap...
bi.BeginInit();
bi.UriSource = uriSource;
bi.UriCachePolicy = new RequestCachePolicy(RequestCacheLevel.Default);
bi.DownloadCompleted += DownloadCompleted;
bi.DownloadFailed += DownloadFailed;
bi.EndInit();
}
// Spin waiting for the bitmap to finish loading...
Dispatcher.Run();
}
private void DownloadFailed(object sender, ExceptionEventArgs e)
{
throw new NotImplementedException();
}
private void DownloadCompleted(object sender, EventArgs e)
{
// The bitmap has been downloaded. Freeze the BitmapImage
// instance so we can hand it back to the UI thread.
var bi = (BitmapImage)sender;
bi.Freeze();
// Hand the bitmap back to the UI thread.
_uiThreadDispatcher.Invoke(DispatcherPriority.Send, new DispatcherOperationCallback(SetBitmap), bi);
// Exit the loop we are spinning in...
Dispatcher.CurrentDispatcher.InvokeShutdown();
}
private object SetBitmap(object arg)
{
LazyImage.Source = (BitmapImage)arg;
return null;
}
So the issue is, doing this after the first time the WorkerThread runs fine, but I never get a callback to the DownloadCompleted or DownloadFailed methods and I have no idea why...
Any ideas?
Not sure but maybe you should try attaching the DownloadCompleted and DownloadFailed event handlers before setting the BitmapImage.UriSource which should trigger the loading of the image, so it might be that it is loaded before your event handlers have been attached (Not the first time around because there the loading takes a while but then the image is cached and will be loaded immediately)
Also: From which class does LazyImageControl inherit so i could test it if that is not it?

Resources