using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace d3
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
pictureBox1.Image = Image.FromFile("C:\\Users\\ocean\\Desktop\\deneme.png");
pictureBox1.Location = new Point(0, 0);
pictureBox2.Image = Image.FromFile("C:\\Users\\ocean\\Desktop\\pul1.png");
}
protected override void OnMouseClick(MouseEventArgs e)
{
Graphics theGraphics = Graphics.FromHwnd(this.Handle);
for (int i = 0; i < 200; i += 5)
{
pictureBox2.Location = new Point(i, 100);
theGraphics.Flush();
System.Threading.Thread.Sleep(50);
pictureBox2.Invalidate();
}
}
}
}
In this code picturebox2 is moving ok but previous locations image stay ON THEuntil the loop finishes. When loop finished the older parts would be erased. I dont want the previous paintings inside the loop I just want to move on pictureBox1. Im new at C# so please help me:) In J2Me I was using flushgraphics but here I tried and it did not work and If you can give an example I would be happy .
In C#, just as in Swing, if you are on the UI or event thread, nothing that you change will be noticed by the user until you are done.
So, if you want to move these, your best bet is to start by getting off the UI thread, by starting a new thread, and then go through your loop.
But, the problem is that you will need to be on the UI thread to make the changes.
This is why your sleep didn't work, you are just putting the event thread to sleep, btw.
Which version of C# are you using? There are many options on creating a thread, and on working with the UI thread.
Here is a link to creating a thread:
http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx
Here is a way to deal with how to get back to the UI thread:
http://blogs.msdn.com/b/csharpfaq/archive/2004/03/17/91685.aspx.
For example, to create a thread you can do this, which came from http://www.rvenables.com/2009/01/threading-tips-and-tricks/
I do my threads this way as I find it simpler to see what is happening.
(new Thread(() => {
DoLongRunningWork();
MessageBox.Show("Long Running Work Finished!");
}) { Name = "Long Running Work Thread",
Priority = ThreadPriority.BelowNormal }).Start();
The most complete answer on how to do your update on the UI thread would be this question:
How to update the GUI from another thread in C#?
UPDATE:
For the part where it states to do long running work, you can add this before the thread block:
TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Then you can do this inside your thread:
(new Task(() =>
{
//copy pixel
pictureBox2.Invalidate(); // You may want to just invalidate a small block around the pixel being changed, or every some number of changes.
}))
.Start(uiScheduler);
By making these changes you could simplify making the change you want, but some of this may be more complex than what you want, which is why I gave some other links to give more information. But, for more on using Task you can look at this excellent blog:
http://reedcopsey.com/2010/03/18/parallelism-in-net-part-15-making-tasks-run-the-taskscheduler/
Related
I have been deploying updates for an application of mine with ClickOnce for a while. While I'm happy to be able to make improvements, I'm a little frustrated with the current progress bar. A little background - I have a XAML window class called "UpdateProgress" that I open when an update is being undertaken for the application. Here's the current code snippet I'm using right now, which does at least notify the user that progress is being made without freezing the application/crashing, but DOES NOT visually update the progress bar:
case UpdateStatuses.UpdateAvailable:
DialogResult dialogResult = System.Windows.Forms.MessageBox.Show("An update is available. Would you like to update the application now?", "Update available", MessageBoxButtons.OKCancel);
if (dialogResult.ToString() == "OK")
{
BackgroundWorker bgUpdate = new BackgroundWorker();
UpdateProgress updateNotify = new UpdateProgress();
bgUpdate.WorkerReportsProgress = true;
bgUpdate.DoWork += (uptSender, uptE) => { UpdateApplication();};
bgUpdate.ProgressChanged += (progSender, progE) => { updateNotify.updateProgress.Value = progE.ProgressPercentage; };
bgUpdate.RunWorkerCompleted += (comSender, comE) => {
updateNotify.Close();
applicationUpdated();
};
updateNotify.Show();
bgUpdate.RunWorkerAsync();
}
break;
Basically, I'm creating a background worker above, which runs the code below:
private static void UpdateApplication()
{
try
{
ApplicationDeployment updateCheck = ApplicationDeployment.CurrentDeployment;
//BackgroundWorker bgWorker = new BackgroundWorker();
//UpdateProgress updateNotify = new UpdateProgress();
//updateCheck.UpdateProgressChanged += (s, e) =>
//{
// updateNotify.updateProgress.Value = e.ProgressPercentage;
//};
//bgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(UpdateComponent.noteUpdates);
//bgWorker.RunWorkerAsync();
//updateCheck.UpdateCompleted += (s, e) =>
//{
// updateNotify.Close();
// applicationUpdated();
//};
//updateNotify.Dispatcher.InvokeAsync(() =>
// {
//updateNotify.Show();
updateCheck.Update();
//});
//return null;
}
catch (DeploymentDownloadException dde)
{
System.Windows.MessageBox.Show("Cannot install the latest version of the application. Please check your network connection, or try again later. Error: " + dde);
//return null;
}
}
Quick explanation, currently I'm only creating an "ApplicationDeployment" instance called "updateCheck" and just having it run the update in this thread. What I've tried attempting before, is loading some of the commented code below, only to see the application crash when updating. Turns out, when debugging with a PROD instance of my application, it's due to the following error:
The calling thread cannot access this object because a different thread owns it.
Now, doing some digging, I've seen quite a few good reads about this. From what I understand, part of the problem is that I'm trying to run this code from a static class separated from my MainWindow and other UI classes. I'm doing this to try to keep my code clean and modular, but apparently, that comes with a price. I realize that one can bind the progress bar's progress percentage if it's in the code-behind of, say, the progress bar's window, but what if I'm trying to stick to running this in the static class I speak of instead? I've tried using things like the Dispatcher methods/BeginInvoke(), but unfortunately to end up with the same result.
Can someone give me the best suggestion on how to update the progress of my progress bar in a window with the percentage progress of an ApplicationDeployment instance's update routine?
Thanks a super ton in advance.
You're mis understanding the cause of your error. Any UI control should be updated from the thread that owns it.
First what you need to wrap is only the line of code that updates your progress bar.
Then you have two ways to wrap your call, either using IProgress<T> or Dispatcher. The former being quite cool as basically you're invoking an Action<T> and Progress<T> ensures to run it in the synchronization context it was instantiated, e.g. the UI thread. This is nice as basically you're abstracting things VS directly using the WPF Dispatcher.
Two really different approaches here, first is declared at caller then callee calls its Report method, second effectively wraps the call to UI in callee.
That's what you are executing during bgUpdate.ProgressChanged that needs to be taken care of.
And now if I were you I'd ditch BackgroundWorker in favor of Task since it's the preferred way to do that now, especially in WPF.
Smallest example using Task and IProgress:
Code:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<StackPanel>
<Button Content="DoWork" Click="Button1_Click" />
<ProgressBar Height="20" x:Name="ProgressBar1" Maximum="1.0"/>
</StackPanel>
</Window>
Code:
using System;
using System.Threading.Tasks;
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
private async void Button1_Click(object sender, RoutedEventArgs e)
{
var progress = new Progress<double>(s => { ProgressBar1.Value = s; });
await Task.Run(() => DoWork(progress));
}
private static async Task DoWork(IProgress<double> progress = null)
{
const int count = 100;
for (var i = 0; i < count; i++)
{
await Task.Delay(50);
progress?.Report(1.0d / (count - 1) * i);
}
}
}
}
Now you're code doesn't even need to know about Dispatcher that is WPF-specific, code could be anywhere, update any framework.
You could also cancel the operation with Task.Run:
https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task.run?view=netframework-4.7.2
This question already has answers here:
Unresponsive UI when using BeginInvoke
(3 answers)
Closed 7 years ago.
I have written a program that counts and the value is represented in the label's text.
The process is started by clicking on the button.
When I start, UI freezes.
I want to solve it by delegate.
Where is my bug?
Code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApplication6
{
public delegate void MyDelegate();
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void DelegateMethod()
{
for (int i = 0; i < 9999999999999; i++)
{
label1.Text = i.ToString();
}
MessageBox.Show("OK");
}
private void button1_Click(object sender, EventArgs e)
{
BeginInvoke(new MyDelegate(DelegateMethod));
}
}
}
It was because your UI element is getting updated so frequently and it will keep doing until loop terminates, if you add Thread.Sleep() after every iteration you can see the behaviour different:
for (int i = 0; i < 9999999999999; i++)
{
label1.Text = i.ToString();
// for example delay 1 second
Thread.Sleep(1000);
}
A more better approach is to use async and await keywords introduced in c# which will do extra work in background, not on UI thread, currently all the processing is getting done on your UI thread, which is causing UI thread to get blocked.But in your case that will not make difference, because here the problem is updating UI very fast which causes it to freeze.
It blocks because you are running it on the same thread as the UI. Also, that many updates to a label will not exactly perform very well - even if being updated from another thread.
If you really want to do that, create a new thread/task and invoke the UI update properly from there.
Because you do it on the UI-Thread. Try Task.Run() instead of BeginInvoke().
The question is pretty trivial: I need to update progress on WPF application while time-consuming calculation is processed. In my tries, I've made some googling and finally based on the first code snippet from this solution: How to update UI from another thread running in another class. And here's my code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Threading;
namespace ThreadTest
{
public class WorkerClass
{
public int currentIteration;
public int maxIterations = 100;
public event EventHandler ProgressUpdate;
public void Process()
{
this.currentIteration = 0;
while (currentIteration < maxIterations)
{
if (ProgressUpdate != null)
ProgressUpdate(this, new EventArgs());
currentIteration++;
Thread.Sleep(100); // some time-consuming activity takes place here
}
}
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void btnStart_Click(object sender, RoutedEventArgs e)
{
WorkerClass wItem = new WorkerClass();
wItem.ProgressUpdate += (s, eArg) => {
Dispatcher.BeginInvoke((Action)delegate() { txtProgress.Text = wItem.currentIteration.ToString(); });
};
Thread thr = new Thread(new ThreadStart(wItem.Process));
thr.Start();
// MessageBox.Show("Job started...");
while (thr.IsAlive == true)
{
Thread.Sleep(50);
}
MessageBox.Show("Job is done!");
}
}
}
The issue is that if I use Dispatcher.Invoke, than the working thread (thr) gets into WaitSleepJoin state after the first cycle pass and does not resume, therefore the entire application freezes. I've googled several suggestions to use Dispatcher.BeginInvoke instead, but in this case the progress is not updated untill the process finishes the work. I guess the issue is related to switching between threads, but cannot get exact point.
This is a classic "Invoke deadlock" scenario. Stack Overflow has a number of existing questions addressing this problem for Winforms, but I could only find one related question in the WPF context (Deadlock when thread uses dispatcher and the main thread is waiting for thread to finish), but that one isn't precisely the same question, or at least doesn't have answers (yet) that would directly address your question, and the question and answers themselves are poorly enough formed that I feel your question warrants a fresh answer. So…
The basic issue is that you have blocked your UI thread waiting on the process to finish. You should never do this. You should never block the UI thread for any reason. It should be obvious that if you wait for any reason in code running in the UI thread, then the UI itself cannot respond to user input or do any sort of screen refresh.
There are lots of possible ways to address this, but the current idiom for dealing with this would be to use async and await, along with Task to run your process. For example:
private async void btnStart_Click(object sender, RoutedEventArgs e)
{
WorkerClass wItem = new WorkerClass();
wItem.ProgressUpdate += (s, eArg) => {
Dispatcher.BeginInvoke((Action)delegate() { txtProgress.Text = wItem.currentIteration.ToString(); });
};
Task task = Task.Run(wItem.Process);
// MessageBox.Show("Job started...");
await task;
MessageBox.Show("Job is done!");
}
Note that while the above declares the async method as void, this is the exception to the rule. That is, normally one should always declare async methods as returning Task or Task<T>. The exception is situations such as this, where the method is an event handler and so is required to match an existing signature where the method must be declared to return void.
I ran your code as it is, and commented out this :
while (thr.IsAlive == true)
{
Thread.Sleep(50);
}
Everything worked as expected.
/Edit after user comment/
To get notified of processing completion, do these changes :
a. public event EventHandler ProgressCompleted; in your WorkerClass.
b.
if (ProgressCompleted != null)
ProgressCompleted(this, new EventArgs());
after your while finishes in Process() method.
c. In your BtnStart_Click before creating thread.
wItem.ProgressCompleted += (s1, eArgs1) =>
{
MessageBox.Show("Job is done!");
};
Getting error: Cross-thread operation not valid: Control 'label1' accessed from a thread other than the thread it was created on.
Code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Windows.Forms;
namespace WindowsFormsApplication2
{
public partial class Form1 : Form
{
string CONNECTING = "Connecting to server...";
string GETTING_DATA = "Getting data...";
string CONNECT_FAIL = "Failed to connect!";
string CONNECT_SUCCESS = "Connection established!";
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Thread t1 = new Thread(run);
t1.Start();
}
public void run() {
label1.Text = CONNECTING;
}
}
}
How do I properly fix this? I've tried using CheckForIllegalCrossThreadCalls = false; but that obviously causes errors.
I'd also like to know how I can stop the thread, since it can't be accessed anymore outside of that function.
Thanks in advance!
Try using BeginInvoke:
public void run()
{
label1.BeginInvoke(new Action(() =>
{
label1.Text = CONNECTING;
}));
}
Only the UI thread can update UI elements in a Windows Forms app. Other threads need to use BeginInvoke to update the UI.
ORGINAL: i assumed this was a WPF app and said to use this.Dispatcher, but Dispatcher isn't in Windows Forms apps.
Accessing a control from different threads
In WinForms App you can ony access directly a Control from the thread it was created.
To do such a task you will need to use InvokeRequired property of a control to see if you must use Invoke inorder to force a call of the action from the original thread.
A public method that might be accessed from any thread including the original would look like this:
public void run() {
if (label1.InvokeRequired) //Is this method being called from a different thread
this.Invoke(new MethodInvoker(()=> label1.Text = CONNECTING));
else //it's cool, this is the original thread, procceed
label1.Text = CONNECTING;
}
But if you are absolutly sure that run() method will be called only from the thread, consider not even checking if InvokeRequired and immediatly call Invoke
Further information: http://msdn.microsoft.com/en-us/library/ms171728(v=vs.80).aspx
Stopping a thread in progress
Simples is to use t1.Abort(); method of a Thread. This will throw and exception forcing it to stop where ever it was. this is great for threads that do not do any long processing so stopping it won't cause any problems.
If you do do proccesing in your thread, which means you can't just stop it in the middle then I suggest you to use a boolean that will indicate that the thread must cancel ASAP.
private bool isCancelRequired = false;
public void run() {
while(true) {
//do long processing..
if (isCancelRequired)
break;
}
}
More advanced methods: http://www.yoda.arachsys.com/csharp/threads/shutdown.shtml
I am implementing a comic reader in C# 4.0, and browsing from one image
to the next takes some time because of some processes I implemented.
Therefore, I implemented it in such a way that the UI thread will show
first the unprocessed image whilst the background thread is processing
the image and will later replace the unprocessed image.
It all works fine but now, some users will crazily like to click next
image continusly and this causes the background worker to processes
all those clicks and display all the images.
WHAT I WANT: if a user clicks multiple times, I want the background
worker to process the last thread only.
WHAT I HAVE DONE: Now, I have implemented a function to check the
number of active threads, if the active threads is greater than 1,
background thread will not process but returns the previous image(THAT
IS NOT GOOD, because the unprocessed image will be one index ahead)
If you have idea please explain to me like a beginner!
private void button4_Click(object sender, EventArgs e)
{
Bitmap b = new Bitmap(this.CurrImage);
if (!shutdown)
{
process_updateThread = new Thread(new ThreadStart(process_update));
process_updateThread.Start();
}
pictureBox1.Image = b; //image will be replaced by worker thread image
pictureBox1.Location = ImageEdit.CalculateLocationImage(b);
SetBackColor(b);
ShowPageCount();
updateNavButtons();
}
void StopThread()
{
if(((IEnumerable)System.Diagnostics.Process.GetCurrentProcess().Threads).OfType<System.Diagnostics.ProcessThread>()
.Where(t => t.ThreadState == System.Diagnostics.ThreadState.Running).Count() > 1)
shutdown = true;
else shutdown = false;
}
I am assuming your long running process is process_update.
You must stop all running process_updates before running the next one. But DON'T USE BOOLEAN VARIABLE TO DO THAT!!! You must use synchronizing objects. Most likely it should be ManualResetEvent.
UPDATE:
This very simple example can give you an idea of multithreading and thread management
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
namespace WindowsFormsExamples
{
public partial class OnlyOneThread : Form
{
List<ManualResetEvent> threadStopEvents; //This will hold stop events for running threads
public OnlyOneThread()
{
InitializeComponent();
threadStopEvents = new List<ManualResetEvent>();
}
private void runThreadBtn_Click(object sender, EventArgs e)
{
ManualResetEvent evt = new ManualResetEvent(false);
ParameterizedThreadStart ts = new ParameterizedThreadStart(this.ThreadFunc);
Thread t = new Thread(ts);
t.Start(evt);
}
private delegate void UptadeThreadCountDelegate(); //This delegate is used by Invoke method
private void UpdateThreadCount()
{
threadcountLbl.Text = threadStopEvents.Count.ToString();
}
protected override void OnClosed(EventArgs e)
{
base.OnClosed(e);
//We must stop threads if they are still running
lock (threadStopEvents) // locking prevents simultaneous list access
{
foreach (ManualResetEvent evt in threadStopEvents)
{
evt.Set(); //signal all events
}
}
}
//This is thread function
private void ThreadFunc(Object obj)
{
ManualResetEvent stopEvent = obj as ManualResetEvent; //cast an object that was passed by Thread.Start()
lock (threadStopEvents) // locking prevents simultaneous list access
{
foreach (ManualResetEvent evt in threadStopEvents)
{
evt.Set(); //signal all events for all other threads to stop
}
threadStopEvents.Add(stopEvent); //Put our event on list
}
if (this.IsHandleCreated) // This is necessary for invocation
this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount)); //Invoke counter update
for (int i = 0; i < 60; i++) // this will run about 1 minute
{
if (stopEvent.WaitOne(0)) // Tests stopEvent and continues
{
//Stop signaled!!! exit!
break;
}
Thread.Sleep(1000); //Sleep 1 second
}
lock (threadStopEvents) // locking prevents simultaneous list access
{
threadStopEvents.Remove(stopEvent); //remove stop event from list
}
if (this.IsHandleCreated) // This is necessary for invocation
this.Invoke(new UptadeThreadCountDelegate(this.UpdateThreadCount)); //Invoke counter update
}
}
}
If you want to run this example you must create WindowsForms project and add Button and label on the form, then use this code to bind to those controls. Note an invocation of forms method. This is necessary when don from non-GUI threads.
I can not see an easy solution to this problem... Multithreading is never easy. Personally, I would propose following (a sort of deviation of the producer/consumer situation):
First have a general counter which signifies the currently to be rendered image (can be a simple int which is incremented for each button pressed)
An ImageMonitor which is nicely locked and has a methods to:
add an image to be rendered (with the current counter) -> this happens for each button pressed
retrieve the image which should be rendered (including the counter of the image)
Process a rendered image
Now we need a continously working Background thread which loops and in every iteration checks the ImageMonitor for the newest image to process, processes the image and returns it back to the ImageMonitor (including the counter)
When the ImageMonitor gets a rendered image from the background renderer, then it can check if the image has the correct counter value, if so then it can swap the current image with the rendered image
This solution is obviously a little complicated. However, it should work. I'm interested in other (easier) solutions.
Good luck