This question already has answers here:
Not updating GUI in time
(2 answers)
WinForm Application UI Hangs during Long-Running Operation
(3 answers)
Accessing UI controls in Task.Run with async/await on WinForms
(6 answers)
Closed 5 years ago.
I have a function which makes process. At the beginning of the function I want to change the text of a label which indicates the state, and once the process ends, change it again.
The fact is that only is shown the final change.
I know I can make a thread for the process but not needed in this case and I merely want to know if there's some tip or trick to accomplish it whitout the use of a thread.
In this case When you change something in UI it does not change until the whole process is completed so as you said you can only see the final state of your label. The trick is simple. You need to use a secondary thread while you are going to update the label for the fist time.
Look at the example below :
class Program
{
private delegate void del();
static void Main(string[] args)
{
del d = updateConsole;
var res = d.BeginInvoke(null, null);
while (!res.IsCompleted)
{
// do the job here
}
d.EndInvoke(res);
Thread.Sleep(1000);
Console.Clear();
Console.WriteLine("Done!");
Console.Read();
}
private static void updateConsole()
{
for (var i = 0; i <= 10; i++)
{
Thread.Sleep(500);
Console.Clear();
Console.WriteLine(i);
}
}
}
This simple technique helps you to separate the first update of the label from the whole process.
Related
This question already has answers here:
How to put delay before doing an operation in WPF
(2 answers)
Is it possible to change views, once during the start of an event handler and once during end?
(4 answers)
Closed 3 years ago.
I'm trying to emulate a process where buttons are sequentially getting set to one colour then back to their previous colour every few seconds.
Problem is, I am not entirely sure how to iterate through a collection without blocking the UI thread... i don't like using thread.sleep but this is what i found on SO.
Anyone aid me? Posting code I have below for Start button click
private void StartTest_Click(object sender, RoutedEventArgs e)
{
//tabControl.SelectedIndex = 3;
// Emulate buttons being processed
Dispatcher.Invoke(() =>
{
new Task(() =>
{
selectedButtons.All(bSelected=>
{
bSelected.Background = resourceDictionary["ProcessingButtonColour"] as Brush;
Thread.Sleep(3000);
bSelected.Background = resourceDictionary["HoverOverColourInactive"] as Brush;
return true;
});
}).Start();
});
}
You shouldn't need Dispatcher.Invoke here if your button is clicked from the UI then your on the UI thread. Just loop through the buttons and change their color. No reason to Select just to return a dummy true value. Also, no reason hardly ever to use a Task constructor, especially not to run work back on the UI thread. Something like this should work:
private async void StartTest_Click(object sender, RoutedEventArgs e)
{
foreach (var button in selectedButtons)
{
button.Background = resourceDictionary["ProcessingButtonColour"] as Brush;
await Task.Delay(3000);
button.Background = resourceDictionary["HoverOverColourInactive"] as Brush;
}
}
This question already has answers here:
Async method not running in parallel
(3 answers)
Closed 3 years ago.
The following seemingly simple scenario is causing me problems:
private List<Task> _Tasks = new List<Task>();
void someMethod() {
//stuff
prepareWork();
Task.WaitAll(_Tasks.ToArray());
//do more stuff
}
private void prepareWork() {
for (int i = 0; i < 2; ++i) {
_Tasks.Add(someWork());
//_Tasks.Add(Task.Run(() => someWork())); //<---- This does work
}
}
private async Task someWork() {
Thread.Sleep(2000);
}
I would expect someWork() to be run asynchronously, but it is not the case. It becomes the case when I replace the _Tasks.Add(someWork()); line with the commented line underneath. It seems to me I am missing something fundamental about the way C#/async and I would appreciate any help.
This is not the answer (and partially incorrect) but leaving as comment by Peter below add a
valid and overlooked point.
Will delete if Peter can put in an answer to the question
When you are adding tasks, you have just created the work to be done. But as you noticed it has not yet started.
_Tasks.Add(someWork());
To run any task you have to call its start method, to run all task in the list you can start them and then wait as you are doing for all to complete.
_task.ForEach(t=>t.Start());
This question already has answers here:
thread get 100% CPU very fast
(5 answers)
Closed 4 years ago.
I have a task to get a piece of c# code to make my CPU go 100% consistently. I have tried infinite loops, big integer calculations, concatenation of numerous very long strings.... everything either goes to 100% for a few moments and then down to like 60% or doesn't go to 100% at all.
Is there a simple piece of code that can achieve this?
Also using Windows 10
You would want to implement threading for this as was previously stated. Your thread would call a method that contains a while(true) loop. For example:
Random rand = new Random()
List<Thread> threads = new List<Thread>();
public void KillCore()
{
long num = 0;
while(true)
{
num += rand.Next(100, 1000);
if (num > 1000000) { num = 0; }
}
}
public void Main()
{
while (true)
{
threads.Add( new Thread( new ThreadStart(KillCore) ) );
}
}
You don't have to add the threads to a list but you may want to if you somewhere down the road want to call Thread.Abort() to kill them off. To do this you would need a collection of some sort to iterate through and call the Abort() method for every Thread instance in the collection. The method to do that would look as follows.
public void StopThreads()
{
foreach (Thread t in threads) { t.Abort(); }
}
use parallel for to maximize the CPU Cores usage and get the best of threading , inside each thread create an infinite loop using while(true) and congratulations
you have **** your CPU :D
This question already has answers here:
execution time calculation
(3 answers)
Closed 6 years ago.
I want to capture the execution time of a particular code block is that possible in c#
Example:
public class DoSomething
{
public void Long_Running_Call()
{
.....
}
public void Medium_Running_Call()
{
.....
}
}
In the main function I want to know the execution time of Long_Running_Call() and Medium_Running_Call().
public static void main()
{
var do_something = New Do_Something();
do_something.Long_Running_Call(); //I want to print the time taken for this function call below
}
You can use System.Diagnostics.Stopwatch:
Stopwatch watch = new Stopwatch();
var do_something = new Do_Something();
watch.Start(); // Start the timer
do_something.Long_Running_Call(); // Long running call
watch.Stop(); // Stop the timer
TimeSpan elapsed = watch.Elapsed;
Of course, this is supposing Long_Running_Call is synchronous and blocking the main thread.
This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 9 years ago.
Short Version :
I need to pass complex data back and forth between threads, 1 thread being a WinForm, the other thread calling an online translator service and changing all the data the Winform uses.
Long Version :
Passing large amounts of data to an online translator service was freezing up my front end for minutes at a time, so I'm trying to move that logic into a thread. The Winform makes extensive use of the data that the online service needs to process and return with new info attached.
I was using this code to kick off the thread :
threadWork tw = new threadWork(); //obj to hold data for thread
tw.settings = frmMain.projectSettings;
tw.CompletedEvent += tw_CompletedEvent; // callback event, returns data
ThreadPool.QueueUserWorkItem(doWork,tw); // kick off thread
receiving callback code :
void tw_CompletedEvent(projectFormat settings)
{
frmMain.projectSettings = settings;
NotifyLoadTransationKeys(frmMain.projectSettings.translationKeys,frmMain.projectSettings.translatedLanguages);
}
which basically created this error :
Cross-thread operation not valid: Control '' accessed from a thread other than the thread it was created on. [on frmMain]
so I found this suggesting an alternative use of [STAThread] [sta = single thread apartment] inside Program.cs (default c# winform entry point)
using System.Threading;
Thread t = new Thread(new ThreadStart(StartNewStaThread));
// Make sure to set the apartment state BEFORE starting the thread.
t.ApartmentState = ApartmentState.STA;
t.Start();
private void StartNewStaThread() {
Application.Run(new Form1());
}
Everything in my C# app starts in 'Program.cs' so I tried the above suggestion like so :
static class Program
{
public static translationUtil TranslationUtil; //location of time intensive webservice
public static projectFormat projectSettings; //data that needs sharing
static void Main() // prog entry point
{
ProgramCode pc = new ProgramCode();
pc.Main();
}
}
class ProgramCode
{
public void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Thread t = new Thread(new ThreadStart(StartNewStaThread));
t.ApartmentState = ApartmentState.STA;
t.Start();
}
private void StartNewStaThread()
{
Application.Run(new Main());
}
}
in the code above I've tried to move the shared resources to 'Program.cs' and then created a new class and thread to hold my winform,but this still gives me cross threading issues (same error as before)! Has anybody got an suggestions as to how to use threads and share data successfully in my situation?
Update : #HenkHolterman answered my question best thus far, but I've come across this code many times after researching the answer he has given me (using "invoke")
if (control.InvokeRequired) {
control.Invoke(new ControlStringConsumer(SetText), new object[]{control, text}); // invoking itself
} else {
control.Text=text; // the "functional part", executing only on the main thread
}
Follow on question... the 'if' statement above appears to just set the text without invoke (on one of the branches of the 'if', should I follow this pattern as well, what is it for?
Your basic solution:
void tw_CompletedEvent(projectFormat settings)
{
frmMain.projectSettings = settings;
frmMain.Invoke( () =>
NotifyLoadTransationKeys(
frmMain.projectSettings.translationKeys,
frmMain.projectSettings.translatedLanguages)
);
}
But when NotifyLoadTransationKeys() takes a lot of time you'll need to break it up.
Edit:
Calls to Invoke() are often surrounded with if (control.InvokeRequired) , a small optimization. But when you are sure you are on another (than the UI) thread you can skip that.