I am trying to retrieve images from media library to a warp panel inside listbox 'lstImageFromMediaLibrary', also am trying that while the images load i show a loading screen using a usercontrol and adding it to popup.child
but i am getting this exceeption 'UnauthorizedAccessException'
when i remove all backgrougWorker related code no such unauthorized access is there....
void backroungWorker_DoWork(object sender, DoWorkEventArgs e)
{
foreach (Picture p in mediaLibrary.Pictures)
{
bitmapImage.SetSource(p.GetThumbnail());
lstBitmapImage.Add(bitmapImage);
}
this.lstImageFromMediaLibrary.ItemsSource = lstBitmapImage;
}
any help is appriciated , i hope i made myself clear....
EDIT:
ok so now m doing this
BackgroundWorker backroungWorker = new BackgroundWorker();
Popup popup = new Popup();
public PanoramaPage1()
{
InitializeComponent();
showpopup();
init();
}
private void init()
{
backroungWorker.WorkerReportsProgress = true;
backroungWorker.DoWork += new DoWorkEventHandler(backroungWorker_DoWork);
backroungWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backroungWorker_RunWorkerCompleted);
backroungWorker.ProgressChanged+=new ProgressChangedEventHandler(backroungWorker_ProgressChanged);
backroungWorker.RunWorkerAsync();
}
void backroungWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Dispatcher.BeginInvoke(() =>
{
popup.IsOpen = false;
}
);
}
void backroungWorker_DoWork(object sender, DoWorkEventArgs e)
{
backroungWorker.ReportProgress(10);
}
void backroungWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.InitializePage();
}
private void showpopup()
{
popup.Child = new SplashScreenControl();
popup.Width = 480;
popup.IsOpen = true;
}
private void InitializePage()
{
MediaLibrary mediaLibrary = new MediaLibrary();
List<BitmapImage> lstBitmapImage = new List<BitmapImage>();
foreach (Picture p in mediaLibrary.Pictures)
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.SetSource(p.GetThumbnail());
lstBitmapImage.Add(bitmapImage);
}
this.lstImageFromMediaLibrary.ItemsSource = lstBitmapImage;
}
but still the progress bar just shows a dot and nothing else.....
You are accessing your User Interface in your DoWork Event. You should be communicating to your application through the Background Worker Events such as the ProgressChanged or the RunWorkerCompleted Events.
From First link:
You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the BackgroundWorker events.
Related
I am currently making a podcast client to download episodes. I have got a listView filled with the episodes for a feed and then when you double click on one it places it into a separate 'downloads' lisview which has a 'name' and a 'progress' column.
The problem I am having is trying to individually update each progress while downloading asynchronously. As I am not sure of how to keep track of the progress for each ListViewItem and how to reference it in the downloadProgressChanged function.
private void lvPodDownloads_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (lvPodEpisodes.SelectedItems.Count == 1) // Check if an item is selected just to be safe
{
ListViewItem item = (ListViewItem)lvPodEpisodes.SelectedItem;
string[] epInfo = (string[])item.Tag;
txtTitle.Text = epInfo[0];
txtDesc.Text = epInfo[1];
try
{
imgFeedImage.Source = new BitmapImage(new Uri((Environment.CurrentDirectory + "\\..\\..\\feedImages\\" + epInfo[3])));
}
catch (Exception) // If it fails to set the image (Eg. It's non-existent) It will leave it blank
{
imgFeedImage.Source = null;
}
}
}
private void lvPodEpisodes_MouseDoubleClick(object sender, MouseButtonEventArgs e) // Downloading the episode in here
{
if (e.ChangedButton == MouseButton.Left) // Left button was double clicked
{
ListViewItem selected = (ListViewItem)lvPodEpisodes.SelectedItem;
string[] epInfo = (string[])selected.Tag;
Uri downloadUrl = new Uri(epInfo[2]);
List<Episode> downloading = new List<Episode>();
downloading.Add(new Episode() { Title = epInfo[0], Progress = "0%" });
lvPodDownloads.Items.Add((new Episode() { Title = epInfo[0], Progress = "0%" }));
using (WebClient client = new WebClient())
{
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
}
}
}
static int intDownloadProgress = new int();
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
intDownloadProgress = e.ProgressPercentage;
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
MessageBox.Show("Download completed!");
}
This is a code sample of the downloading section of the program.
Here is an image of what I have so far:
https://s33.postimg.cc/gthzioxlr/image.png
You should add an extra argument to your ProgressChanged method.
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e, Episode curEpisode)
{
curEpisode.Progress = $"{e.ProgressPercentage} %";
}
And to modify the handler setting like that:
List<Episode> downloading = new List<Episode>();
var newEpisode = new Episode() { Title = epInfo[0], Progress = "0%" };
downloading.Add(newEpisode);
lvPodDownloads.Items.Add(newEpisode);
using (WebClient client = new WebClient())
{
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler((sender, e) => ProgressChanged(sender, e, newEpisode));
}
The static property intDownloadProgress is then useless.
You should also think about using an observable collection for the episode list and using it for the binding via the XAML code.
background worker in asp.net does not write the content to the web UI when background worker completed. please tell me the reasons why. and how to recover.???
static BackgroundWorker bwProcess;
[WebMethod()]
public static int GetProgress()
{
return Percentage;
}
background worker starts when click event happen
protected void btnClick_Click(object sender, EventArgs e)
{
bwProcess = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
bwProcess.DoWork += new DoWorkEventHandler(bwProcess_DoWork);
bwProcess.ProgressChanged += new ProgressChangedEventHandler(bwProcess_ProgressChanged);
bwProcess.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bwProcess_RunWorkerCompleted);
bwProcess.RunWorkerAsync("AsyncWorker");
}
do work event for the backgroundworker
void bwProcess_DoWork(object sender, DoWorkEventArgs e)
{
bwProcess.ReportProgress(1);
for (int i = 0; i <= 100; i++)
{
if (bwProcess.CancellationPending)
{
e.Cancel = true;
return;
}
bwProcess.ReportProgress(i);
Thread.Sleep(20);
}
e.Result = "100 %";
}
this part is not working. it run nut there is no response
void bwProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Response.WriteFile("D:\\Samples.xlsx");
}
You've passed something to e.Result in DoWork, but you don't anything with it in RunWorkerCompleted.
void bwProcess_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
var text = e.Result as string;
Response.Write(text);
Response.WriteFile("D:\\Samples.xlsx");
}
I have wcf servise that Update db it is takes 10-15 sec,and i wont to run/show my form with loading/waitting statusbar while servise working, and when service is finished i need to close the watting form.
My problem is when i run ShowDialog(); it is get stuck on it , and don't go to my service.
What i doing wrong here?
My code
My function
public static void UpdateSNXRATES(object sender, EventArgs e)
{
WaitForm waitF = new WaitForm();
waitF.ShowDialog();//here it stuck
using (var Server = new ServiceReference.Service1Client())
{
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success=Server.UpdateSNXRATES();
}
waitF.Close();
}
My WaitForm code
public partial class WaitForm : Form
{
public WaitForm()
{
InitializeComponent();
}
private void WaitForm_Load(object sender, EventArgs e)
{
radWaitingBar1.StartWaiting();
radWaitingBar1.WaitingSpeed = 100;
radWaitingBar1.WaitingStep = 5;
}
}
ShowDialog() is a blocking call, i.e. the current thread will keep waiting on this line until the form is closed (by the user). You should show your WaitForm on a different thread than the main application thread, combined with Invoke() call to ensure that you don't do illegal cross-thread operations. You can use BackgroundWorker component to load and show your WaitForm on a different thread.
Alternately and preferably, you should move your service initialization and running code to the BackgroundWorker. That will ensure you don't need any Invokes.
Example
ServiceReference.Service1Client Server;
WaitForm waitF;
public static void UpdateSNXRATES(object sender, EventArgs e)
{
BackgroundWorker bw = new BackgroundWorker();
bw.WorkerReportsProgress = true;
bw.DoWork += bw_DoWork;
bw.RunWorkerCompleted += bw_RunWorkerCompleted;
bw.RunWorkerAsync();
waitF = new WaitForm();
waitF.ShowDialog();
}
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
Server = new ServiceReference.Service1Client();
Server.ClientCredentials.Windows.ClientCredential.Domain = strDomain;
Server.ClientCredentials.Windows.ClientCredential.UserName = strUser;
Server.ClientCredentials.Windows.ClientCredential.Password = strPassword;
success = Server.UpdateSNXRATES();
}
static void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
waitF.Close()
}
I have created a splash screen for a WinForm app. Everything works well until the splash screen is just a form with a background image and a label which has a static text - "Loading..."
I want to update the label continuously (with small delay in between) with texts - "Loading","Loading.","Loading.." and "Loading...". For this I have put the following code in my SplashScreen form:
private void SplashScreen_Load(object sender, EventArgs e)
{
lblLoading.Refresh();
lblLoading.Text = "Loading.";
Thread.Sleep(500);
lblLoading.Refresh();
lblLoading.Text = "Loading..";
Thread.Sleep(500);
lblLoading.Refresh();
lblLoading.Text = "Loading...";
Thread.Sleep(500);
}
Now the Splash Screen doesn't appear until the label in it gets updated to "Loading..."
Please help to let me know what I am doing wrong.
Code in my HomeScreen:
public HomeScreen()
{
//....
this.Load += new EventHandler(HandleFormLoad);
this.splashScreen = new SplashScreen();
}
private void HandleFormLoad(object sender, EventArgs e)
{
this.Hide();
Thread thread = new Thread(new ThreadStart(this.ShowSplashScreen));
thread.Start();
//...Performing tasks to be done while splash screen is displayed
done = true;
this.Show();
}
private void ShowSplashScreen()
{
splashScreen.Show();
while (!done)
{
Application.DoEvents();
}
splashScreen.Close();
this.splashScreen.Dispose();
}
EDIT:
As suggested by some users here I have put the startup tasks in background thread and now I am displaying the Splash Screen from the main thread. But still the same issue persist. Here is the updated code of HomeScreen form:
public HomeScreen()
{
//...
this.Load += new EventHandler(HandleFormLoad);
}
private void HandleFormLoad(object sender, EventArgs e)
{
this.Hide();
SplashScreen sc = new SplashScreen();
sc.Show();
Thread thread = new Thread(new ThreadStart(PerformStartupTasks));
thread.Start();
while (!done)
{
Application.DoEvents();
}
sc.Close();
sc.Dispose();
this.Show();
}
private void PerformStartupTasks()
{
//..perform tasks
done = true;
}
and here's the Splash Screen :
private void SplashScreen_Load(object sender, EventArgs e)
{
lblLoading.Update();
lblLoading.Text = "Loading.";
Thread.Sleep(500);
lblLoading.Update();
lblLoading.Text = "Loading..";
Thread.Sleep(500);
lblLoading.Update();
lblLoading.Text = "Loading...";
Thread.Sleep(500);
}
You want a BackgroundWorker that posts ProgressChanged event, which will update the splash screen. The progress changed object could be a string, for example, that you'll display on your splash screen (back on the GUI thread).
You should handle the splash screen in the main thread, and the background work of initialising in the background thread (just as logixologist commented).
That said, the reason that your changed message doesn't show up is because the main thread is busy so it doesn't handle the events that redraws the control. Calling DoEvents in a background thread will only handle messages in that thread, and the messages to update the splash screen is in the main thread.
The Refresh method only invalidates the control, which would cause it to be redrawn if the main thread handled the event. You can use the Update method to force the redraw of the control:
private void SplashScreen_Load(object sender, EventArgs e)
{
lblLoading.Text = "Loading.";
lblLoading.Update();
Thread.Sleep(500);
lblLoading.Text = "Loading..";
lblLoading.Update();
Thread.Sleep(500);
lblLoading.Text = "Loading...";
lblLoading.Update();
}
But, this is only a workaround for the current code. You should really make the main thread handle the messages.
Thanks to all for answering my questions. Finally my issue is solved ! I changed my code such that start-up tasks are now being performed on a separate thread and splash screen is displayed from the Home Screen (main) thread. In the home screen I made use of Backgroundworker to update the 'Loading...' label.
I am posting my code here hoping it may also help someone in future..
For the Home Screen code plz see the EDIT part in my question. Here's the code of Splash Screen :
public SplashScreen()
{
InitializeComponent();
backgroundWorker1.WorkerReportsProgress = true;
backgroundWorker1.WorkerSupportsCancellation = false;
lblLoading.Text = string.Empty;
}
private void SplashScreen_Load(object sender, EventArgs e)
{
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
for (int i = 1; i <= 20; i++)
{
System.Threading.Thread.Sleep(200);
worker.ReportProgress(i);
}
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string dots = string.Empty;
for (int k = 1; k <= e.ProgressPercentage; k++)
{
dots = string.Format("{0}..",dots);
}
lblLoading.Text = ("Loading" + dots);
}
You have to define a background worker in your splash screen form.
Here is an example of what your splash screen could look like :
public partial class SplashScreenForm<T> : Form
{
private BackgroundWorker _backgroundWorker;
private Func<BackgroundWorker, T> _func;
private T _funcResult;
public T FuncResult { get { return _funcResult; } }
public SplashScreenForm(Func<BackgroundWorker, T> func)
{
this._func = func;
InitializeComponent();
this.label1.Text = "";
this._backgroundWorker = new BackgroundWorker();
this._backgroundWorker.WorkerReportsProgress = true;
this._backgroundWorker.DoWork += new DoWorkEventHandler(_backgroundWorker_DoWork);
this._backgroundWorker.ProgressChanged += new ProgressChangedEventHandler(_backgroundWorker_ProgressChanged);
this._backgroundWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_backgroundWorker_RunWorkerCompleted);
_backgroundWorker.RunWorkerAsync();
}
private void _backgroundWorker_DoWork(object sender, DoWorkEventArgs e)
{
var worker = sender as BackgroundWorker;
if (worker != null)
{
_funcResult = this._func.Invoke(worker);
}
}
private void _backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.UserState != null)
{
this.label1.Text = e.UserState.ToString();
}
}
private void _backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.Close();
}
}
You can design it the way you want, maybe a pretty gif image, or whatever you can think of.
Call it this way :
private void HandleFormLoad(object sender, EventArgs e)
{
this.Hide();
var splash = new SplashScreenForm<bool>(PerformTask);
splash.ShowDialog(); // function PerformTask will be launch at this moment
this.Show();
}
private bool PerformTask(BackgroundWorker worker)
{
//...Performing tasks to be done while splash screen is displayed
worker.ReportProgress("loading..");
}
I cannot figure out how to catch the Navigating event on the WebBrowser control. Basically I'm trying to figure out how trigger the progress bar to show when a user clicks a link on a page.
Here is the code I use to show the progress bar and then hide it on page loaded. Can someone help me out with the event handler for Navigating?
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
progressBar.IsIndeterminate = true;
progressBar.Visibility = Visibility.Visible;
webBrowser.Navigate(new Uri(MY_URL, UriKind.Absolute));
webBrowser.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(PageLoadCompleted);
webBrowser.Navigating = ?
}
private void PageLoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
{
progressBar.IsIndeterminate = false;
progressBar.Visibility = Visibility.Collapsed;
}
The documentation you seek is here. You can write
webBrowser.Navigating += webBrowser_Navigating;
// ...
void webBrowser_Navigating( object sender, NavigatingEventArgs e )
{
// ...
}
The answer of by VisualStuart helped me solve my problem.
My now working code is as below :
private void MyButton1_Click(object sender, RoutedEventArgs e)
{
MyprogressBar.IsIndeterminate = true;
MyprogressBar.Visibility = Visibility.Visible;
string site = MyTextBox1.Text;
webBrowser1.Navigate(new Uri(site, UriKind.Absolute));
webBrowser1.Navigating += webBrowser1_Navigating;
webBrowser1.LoadCompleted += new System.Windows.Navigation.LoadCompletedEventHandler(webBrowser1_LoadCompleted);
}
private void webBrowser1_Navigating(object sender, NavigatingEventArgs e)
{
MyTextBox1.Text = e.Uri.ToString();
MyprogressBar.IsIndeterminate = true;
MyprogressBar.Visibility = Visibility.Visible;
}