i have an Infragistics carousel control which i want to call "next" on every 5 seconds. However im not sure how to do this without a while true.
Any help would be great, thanks!
Currently its kicked off from a click, starting a task within a while true. Obviously this i what i want to avoid.
private void GoToNext(object sender, MouseButtonEventArgs e)
{
while (true)
{
Task task = new Task(() => MyCarousel.Dispatcher.BeginInvoke(new next(goToNext), null));
task.Start();
}
}
private bool goToNext()
{
Thread.Sleep(15);
MyCarousel.ExecuteCommand(Infragistics.Windows.Controls.XamCarouselPanelCommands.NavigateToNextItem);
return true;
}
Timers are used for this in general, sitting in the background and triggering every so often. There are a number in .NET (in System.Timers and elsewhere) and which one is best depends on your particular scenario.
Related
The application is a machine control, so it needs access to ui to show status etc. (I know, goes against the recommendation to separate UI and work code, but it is what it is, at least for now). The issue boils down to this: When one button event handler is not finished, another button needs to be clicked twice. First click gives the focus to the button, next click fires the event.
Here is the issue simplified to extreme. There are two buttons and a label. Stop button needs two clicks to stop the machine:
bool Stop = true;
private void Start_button_Click(object sender, EventArgs e)
{
RunMachine();
}
private void Stop_button_Click(object sender, EventArgs e)
{
Stop = true;
}
private void RunMachine()
{
Stop = false;
Status_label.Text = "Running";
do
{
Application.DoEvents();
Thread.Sleep(50);
}
while (!Stop);
Status_label.Text = "Stopped";
}
How can I make the button to react to the first click?
DoEvents() is bad. Don't use it.
If you have to use it (e.g. as workaround), then you are adding technical debt and likely to pay in the future, similar to your case.
A better approach is to run work inside the task and use cancellation token, but in your case the minimum modification required is this (add async modifier to a method):
while (!Stop)
{
await Task.Delay(50);
// or
await Task.Run(() => Thread.Sleep(50));
}
The UI should be responsive now.
The latter is simulating synchronous code, put it instead of Sleep, don't forget to invoke if there you have to modify UI.
Thank you! I wasn't aware of the implications of Doevents, and using async and await is just as simple. I added a counter to show myself that the toy example is doing what I think it is. To make the answer complete and to help other noobs like me that might search answers for the same issue, here is the full example again. This works as wanted (stops with one click) and doesn't leave the RunMachine() running if the main form is closed without clicking stop. (My real application has enough code in the form closing event to prevent that, but I certainly wasn't aware of the trap.)
bool Stop = true;
private async void Start_button_Click(object sender, EventArgs e)
{
await RunMachine();
}
private void Stop_button_Click(object sender, EventArgs e)
{
Stop = true;
}
internal async Task RunMachine()
{
Status_label.Text = "started";
Stop = false;
int i=0;
do
{
await Task.Delay(500);
Status_label.Text = i.ToString();
i++;
} while (!Stop);
Status_label.Text = "Stopped";
}
Im trying to make a simple application to learn some things in c# (Visual Studio).
For now i am building a music player, and one of the actions is fading out the music at the button click event.
I've got no problem with building a fade-out part, i made a while loop and put the volume down with 1% eacht time the loop is running. Also i update a label with the fade value.
Only problem is, for slowing down the fading i'm using the Thread.Sleep event, and that part is freezing my application, and also is blocking any updates to my text label with the fade value.
The fading is working fine, so the only part I have to work on is another option to build some delay in. On some topics over here i did read about the timer, and i added a timer component in Visual Studio. Only problem, I am new to c# and don't know how to use it correctly in this while loop.
Can anybody give me some help?
The current code is:
private void BtnPodiumtune1Fadeout_Click(object sender, EventArgs e)
{
PlayerPodiumtune1.settings.volume = 100;
fade1 = 100;
while (fade1 != -1)
{
PlayerPodiumtune1.settings.volume = fade1;
Fadelevel1.Text = fade1.ToString();
System.Threading.Thread.Sleep(30);
fade1 = fade1 - 1;
}
PlayerPodiumtune1.Ctlcontrols.stop();
}
You could use a pattern like this instead of a timer. A timer is a fine way to go, just throwing this option out there:
private async void button_Click(object sender, EventArgs e)
{
if (Monitor.TryEnter(sender))
{
int fade1 = 1000;
while (fade1 != -1)
{
await Task.Delay(30);
fade1--;
}
}
}
So sender is the button, and Monitor.TryEnter prevents the function from being run again until the function is done. async tells the framework that this function can be executed asynchronously and is necessary for await. await returns control of the thread to the UI until the task is done.
PS--You're going to need something like Monitor.TryEnter to prevent re-entrancy in a timer-based solution as well, by the way.
This is a Console Application in C#:
using System;
namespace WaitAsync
{
class Program
{
static void Main(string[] args)
{
bool ok = false;
Console.Write("EnterTime (Seconds): ");
int time = Convert.ToInt32(Console.ReadLine()) * 1000;
while (ok != true)
{
System.Threading.Thread.Sleep(time);
ok = true;
Console.WriteLine("Waiting Time Just Finished");
}
Console.ReadLine();
}
}
}
Assuming that a client app gets data from a server nearly in real time. What is the more efficient way to continuously update the UI based on the retrieved data. Think of multiple xaml controls, like texts that show numbers. Those get updated as long as the application is running. They never stop unless the user decides it. (let's say by pressing a stop button or exit the app)
Below I have a simple example utilizing async and await keywords. Is that a good way for my scenario? Or for example BackgroundWorker would be a better way?
private async void Button_Click_Begin_RT_Update(object sender, RoutedEventArgs e)
{
while(true)
textField1.Text = await DoWork();
}
Task<string> DoWork()
{
return Task.Run(() =>
{
return GetRandomNumberAsString();
});
}
*for the sake of simplicity I use code-behind and not mvvm in my example
Your code is more or less OK if your GetRandomNumberAsString() takes at least 15ms to complete.
If it takes less than that, and you want to minimize update latency i.e. you don't want to just wait, you might want to (1) replace your per-operation Task.Run with an endless loop that completely runs in a background thread (2) Implement throttling mechanism in that loop, and only update your GUI (using e.g. Dispatcher.BeginInvoke()) at around 30-60Hz.
P.S. The exact mechanism how you update your GUI (databinding + INotifyPropertyChanged, or directly like in your code) is not relevant for performance.
Update: here's example (untested)
static readonly TimeSpan updateFrequency = TimeSpan.FromMilliseconds( 20 );
void ThreadProc()
{
Stopwatch sw = Stopwatch.StartNew();
while( true )
{
string val = GetRandomNumberAsString();
if( sw.Elapsed < updateFrequency )
continue; // Too early to update
sw.Restart();
Application.Current.Dispatcher.BeginInvoke( () => { textField1.Text = val; } );
}
}
Basically i am running a programm that executes a method that is repeated several times (for example 7 times), but i need an option to cancel the CURRENTLY run one of it, but still allow new ones to start.
My issue is that the programm ends as soon as i hit the cancel button. So i seem to be missing something.
Main:
for(int i = 0; i < 7; i++)
{
cts = new CancellationTokenSource();
taskUbung = Task.Factory.StartNew(async() =>
{
await doSomething();
}, cts.Token);
}
Button:
private void buttonSkipUbung_Click(object sender, RoutedEventArgs e)
{
cts.Cancel();
}
So if i am hitting the button on the 3rd round of doSomething(), the remaining 4 will never execute.
What do i have to change for my desired behavior? I could just use some booleans and return in doSomething(), but i figured this would be cleaner and more responsive, if it works that is.
You need to keep track of the tokens you are creating in some kind of list. Otherwise you only remember the last one and call cancel only on that one
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
asp.net update UI using multi-thread
I started a thread to process on background.And i want to change my label on page after finished proceess.
But my value doesn't change.
my sample :
protected void Page_Load(object sender, EventArgs e)
{
new Thread(() => ActionStart()) { IsBackground = true }.Start();
}
bool _shouldStop = false;
public void ActionStart()
{
while (!_shouldStop)
{
// ....
requestStop();
}
//thread finished
ChangeValue();
}
private void ChangeValue()
{
lab.Text = "Changed";
}
private void requestStop()
{
_shouldStop = true;
}
I'm afraid running this code on a Thread won't help you because you can't make sure the thread will complete before it's to late considering the page life cycle. Generally, the last chance you got to alter a control's value is the it's PreRender event, but that depends on how it has been developed.
However, if you need to do processing in parallel, you still can use a Parallel.Foreach, for instance, inside a page event like PageLoad to take advantage of parallelism without being asynchronous (Parallel.Foreach will only return when all threads complete).