This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 9 years ago.
I have a problem. I'm trying to make seekbar for BASS in C#.NET (WPF) but when I'm starting a new Thread it can't get access to modify value of my Slider or Label (with current song position value). Here is a Code:
//class:
Thread seekbar;
public Window1()
{
InitializeComponent();
Bass.BASS_Init(-1, 44100, BASSInit.BASS_DEVICE_DEFAULT, IntPtr.Zero);
seekbar = new Thread(new ThreadStart(this.ThreadTask));
seekbar.IsBackground = true;
seekbar.Start();
}
private void ThreadTask()
{
int value = (int)Bass.BASS_ChannelGetPosition(music);
while (true)
{
MusicSeekBar.Value = value; //MusicSeekBar is mine Slider
CurrentValue.Content = value; //CurrentValue is a Label
}
}
I always get an error that thread can't get access to this two objects. Thanks for help in advice.
You need to call the MusicSeekBar & CurrentValue in a Dispatcher beceause the new thread doesn't have access to them.
Dispatcher.BeginInvoke(new Action(() =>
{
MusicSeekBar.Value = value; //MusicSeekBar is mine Slider
CurrentValue.Content = value; //CurrentValue is a Label
}));
Related
This question already has answers here:
How to create a Flashing and Normal Background Visual States for a Border control
(2 answers)
Closed 22 days ago.
I have been trying to get a border in my wpf application(c#) to flash red and blue when you input the wrong password.
my code:
//This method executes when you enter the wrong password
void Alert()
{
Count = 0;
while (Count <= 5)
{
Border_.BorderBrush = Brushes.DarkRed;
//Timer here
Border_.BorderBrush = Brushes.DarkBlue;
//Timer here
Count++;
}
}
I have tried using await, Thread.Sleep(1000), Task.Delay(1000) and Timers but nothing worked. I searched for any similar question but could not find any solution that worked for me. (This question didnt work for me either: How to create a Flashing and Normal Background Visual States for a Border control)
This is the code-behind example, without visual states;
public Task Alert()
{
return Task.Run(() =>
{
int Count = 0;
while (Count <= 5)
{
Application.Current.Dispatcher.Invoke(() => Border_.BorderBrush = Brushes.DarkRed);
//Timer here
Thread.Sleep(1000);
Application.Current.Dispatcher.Invoke(() => Border_.BorderBrush = Brushes.DarkBlue);
//Timer here
Thread.Sleep(1000);
Count++;
}
});
}
And you can call with;
await Alert();
Also, do not forget to set BorderThickness.
I am in a bottleneck finishing a GUI in Windows Forms C#.
I am 100% new doing this and I think that I am mixing and messing around. Someone could help me please?
I am embedding an artificial vision application (developed in HALCON software and exported to C#). I resume this app in one class with one method having three outputs (couple of images and a string).
I put this class inside a while loop with other classes to iterate and interact with the outputs from the vision app till state statusFile is 1 to exit the loop.
Firstly I was using only the mean thread and my GUI got unresponsive when inside the while loop was getting into the vision.
Snippet of Start button:
public string pathFile { get; set; } // THIS DATA COMES FROM PREVIOUS WFORM
public DataTable dataLonas { get; set; }
public string namePro { get; set; }
public Thread Run_thread = null, run1 = null;
public static AutoResetEvent myResetEvent
= new AutoResetEvent(false); // initially set to false.
public VentanaIniciarProceso3()
{
InitializeComponent();
}
private void button_start_process_Click(object sender, EventArgs e)
{
string name_button = button_start_process.Text;
if (name_button == "Start")
{
boton_iniciar_proceso1.Text = "Pause"; // CHANGE THE LABEL
// instead having more buttons
run1 = new Thread(t => //HERE THE NEW THREAD
{
while (statusFile == 0) //
{
HObject ho_IMAGE_OPERARIOS = null;
HObject ho_ActualImageTrim = null;
HTuple hv_READ_OCR_STRING = new HTuple();
// HALCON CLASS
(hv_READ_OCR_STRING, ho_ActualImageTrim, ho_IMAGE_OPERARIOS) =
LONASapp.action(hv_AcqHandle, hv_AcqHandle_2, pathFile, namePro);
string codigo = hv_READ_OCR_STRING.ToString();
// EVAL CODE
int aux_aviso = EvalCodigoBeta.analizarAvisoBeta(codigo,
dataLonas, pathFile, namePro);
// EVAL FILE CLASSFICHERO.
// statusFichero para 1 o 0
// Variable que indique si fuerza operario
statusFile = EvalFichero.checkCarga(dataLonas, pathFile, namePro);
statusFile = ContinuarSalirProyecto.continuarSalir(statusFile);
// IF statusFile==1 It Will exit
}
})
{ IsBackground = true };
run1.Start(); // START IN BACKGROUND THE LOOP WITH THE CLASSES
}
else if (name_button == "Pause")
{
myResetEvent.WaitOne(); // SAME BUTTON WITH LABEL CHANGED TRYING
// TO PAUSE THE THREAD
boton_iniciar_proceso1.Text = "Resume";
}
else
{
myResetEvent.Set(); // SAME BUTTON WITH LABEL CHANGED
// TO "RESUME" TO UNPAUSE
boton_iniciar_proceso1.Text = "Pause";
}
}
After doing this change, the GUI gets responsive which is nice and the correct way I am sure is using different threads. But when clicking again to the button which has changed the label to "Pause", it does not pause the thread run1, it continues… and now the GUI gets paused/unresponsive when cause of myResetEvent.WaitOne();
Could I ask you for help please? I am confused also and do not know where to continue or what to change…
Thanks a lot in advance. I really want to close this thing after 5 days not coming with the good idea.
This question already has answers here:
progress bar not progressing
(4 answers)
Closed 7 years ago.
I have a method getPlugins that takes quite a long time to run. Essentially it's parsing a very large log file. I know the log file goes from time 0 to time 24. I would like to update a ProgressBar based on the current time. Here's the structure of my code, but the bar only seems to be updated once my loop is finished... How can I fix this?
private void getPlugins(String filePath)
{
var w = new Window2();
w.Show();
w.progress.Value = 0;
List<String> pluginNames = new List<String>();
string strLine;
// Read the file and display it line by line.
System.IO.StreamReader file = new System.IO.StreamReader(filePath);
while ((strLine = file.ReadLine()) != null)
{
// Do stuff....
float time; // Here I have time as a float from 0 to 24
w.progress.Value = time;
}
file.Close();
w.progress.Value = 24;
w.Close();
}
Basically the idea is that you can not update UI elements directly from a non UI thread. WPF has a Dispatcher class that gives u access to UI elements and using this you can update the UI elements like below code
Application.Current.Dispatcher.Invoke(DispatcherPriority.ApplicationIdle, (Action)(() =>
{
w.progress.Value = time;
}));
This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 8 years ago.
catch (Exception ex)\\error
{
clsLogs.LogError("Error: " + ex.Message + this.Name + " || ImportData");
result = false;
}
;Cross-thread operation not valid: Control 'cmbDeviceName' accessed from a thread other than the thread it was created on
You can do it like this using Invoke:
this.Invoke((MethodInvoker)delegate()
{
//// your code
});
class YourForm : Form
{
private SynchronizationContext synchronizationContext ;
public YourForm()
{
this.synchronizationContext = SynchronizationContext.Current;
//the rest of your code
}
}
and then, when you need to do some thread-unsafe form actualizations you should use something like this:
synchronizationContext.Send(new SendOrPostCallback(
delegate(object state)
{
textBoxOut.Text = "New text";
}
), null);
source codeproject
This question already has answers here:
Accessing UI (Main) Thread safely in WPF
(3 answers)
Closed 8 years ago.
why this code wont work without Dispatcher.RunAsync and what does it do? without Dispatcher its throwing error at copying value to textv.Text " thats its on different thread"
async void Current_GeofenceStateChanged(GeofenceMonitor sender, object args)
{
var reports = sender.ReadReports();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
foreach (var report in reports)
{
GeofenceState st = report.NewState;
Geofence gf2 = report.Geofence;
if (st == GeofenceState.Entered)
{
textv2.Text = "Hello"; //XAML TEXT
}
else if(st==GeofenceState.Exited)
{
textv2.Text = "Bye";
}
}
});
}
The Event Current_GeofenceStateChanged is being fired outside of the GUI thread and only the GUI thread can change GUI elements. Dispatcher.RunAsync says the code inside should run on the GUI thread so it works.
if you put the result on a string variable it will work if you only put:
Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => textv2.Text = StringVariable;);
EDIT: I only noticed that you have XAML code later you can just put the string on a property and bind the property to the text value of the text box letting you free from the Dispatcher.
<TextBox Text="{Binding StringVariable}"/>
and on the code just have
public string StringVariable { get; set; }
than on the method just set the value to the property
StringVariable = "bla bla";