So I am using AI, to transcribe some text in azure, I am copying the text into background chipboard (That I found here), I am retrieving the text and sending it to a second windows
The problem is that Windows gives me this issue
System.InvalidOperationException: 'The calling thread must be STA, because many UI components require this.'
this is the code that is breaking things
private void SpeechRecognizer_SessionStopped(object? sender, SessionEventArgs e)
{
var sb = new StringBuilder();
foreach (var item in Words)
{
sb.Append(item);
}
BackgroundClipboard.SetText(sb.ToString());
if (!string.IsNullOrEmpty(BackgroundClipboard.GetText()))
{
var spellWindow = new SpellCheckWindow();
spellWindow.Show();
}
}
private void SpeechRecognizer_SessionStarted(object? sender, SessionEventArgs e)
{
}
private void SpeechRecognizer_Recognized(object? sender, SpeechRecognitionEventArgs e)
{
if (e.Result.Reason == ResultReason.RecognizedSpeech)
{
foreach (var item in e.Result.Text)
{
Words.Add(item);
}
}
}
private void SpeechRecognizer_Recognizing(object? sender, SpeechRecognitionEventArgs e)
{
}
}
Try create/show the window via the main dispatcher like this
Application.Current.Dispatcher.Invoke(() => {
var spellWindow = new SpellCheckWindow();
spellWindow.Show();
});
Related
With this code it is not letting me remove the connected IP with .Remove How can I remove the client from the list on disconnection using the DataGridView? I have also tried Listview but again i had the same issue even with the full row selection. I cant seem to have found any other posts that have the issue I am using SuperSimpleTcp for this due to the less dependent networking I have also tried to add it as a DataGridViewRow but no luck the client will remain even if disconnected. If anyone has experience it would be nice to help out. Also apologies if the code is messy at the moment but i have been reiterating this class for a bit. I can get the client to be added to the view np but as i said removing the client is the primary issue.
public void Lista()
{
sert = new SimpleTcpServer("0.0.0.0", 8080);
try
{
if (metroToggle1.Checked == true)
{
sert.Start();
}
else if(metroToggle1.Checked == false)
{
sert.Stop();
}
}
catch
{
}
sert.Events.ClientConnected += Events_ClientConnected;
sert.Events.ClientDisconnected += Events_ClientDisconnected;
sert.Events.DataSent += Events_DataSent;
}
private void metroToggle1_CheckedChanged(object sender, EventArgs e)
{
if (metroToggle1.Checked == true)
{
sert.Start();
}
else if (metroToggle1.Checked == false)
{
sert.Stop();
}
}
private void Events_DataSent(object? sender, DataSentEventArgs e)
{
}
private void Events_ClientDisconnected(object? sender, ConnectionEventArgs e)
{
var milko = $"Client {e.IpPort} has Disconected!";
notifyIcon1.Icon = SystemIcons.Application;
notifyIcon1.BalloonTipText = milko;
notifyIcon1.ShowBalloonTip(2000);
dataGridView1.Invoke(new Action(() => dataGridView1.Rows.Remove(e.IpPort)));
}
private void Events_ClientConnected(object? sender, ConnectionEventArgs e)
{
var milko = $"New Client {e.IpPort} has connected!";
notifyIcon1.Icon = SystemIcons.Application;
notifyIcon1.BalloonTipText = milko;
notifyIcon1.ShowBalloonTip(2000);
dataGridView1.Invoke(new Action(() => this.dataGridView1.Rows.Add(e.IpPort)));
}
could please help with that. I can not subscribe for event fired by an object from another Task.
Note: If i took the code outside the Task, it works fine. you can see the commented code
private void Form1_Load(object sender, EventArgs e)
{
_machines.Add(new Machine() { Ip = "192.168.1.10", Name = "Machine_01", Status = "Connected" });
dgvMachines.DataSource = _machines;
}
private void startLiveMonitoringToolStripMenuItem_Click(object sender, EventArgs e)
{
//if (_machines.Count <= 0) return;
//_fpMachine = new ZktFingerPrint(_machines[0].Ip, _machines[0].Name);
//_fpMachine.Connect();
//_fpMachine.EnableLiveFingerPrintDetection();
//_fpMachine.NewFingerPrintDetected += FpMachine_NewFingerPrintDetected;
foreach (var machine in _machines)
{
Task.Factory.StartNew(() =>
{
IFingerPrintMachine fpMachine = new ZktFingerPrint(machine.Ip, machine.Name);
fpMachine.Connect();
fpMachine.EnableLiveFingerPrintDetection();
fpMachine.NewFingerPrintDetected += FpMachine_NewFingerPrintDetected;
});
}
}
private void FpMachine_NewFingerPrintDetected(object sender, FingerPrintEventArgs e)
{
var fpr = new FingerPrintRecord(e.FingerPrintDateTime, e.UserId);
dgvMonitor.Rows.Add("Machine_01", fpr.FingerPrintDateTime, fpr.UserSn);
}
I am trying to build a scratch-like application to simulate block-based programming approach. I want the user to add the commands to command pool(queue) and run them in order when the user clicks on the "RUN" button.
I researched on the internet and found queueing is possible by Action lists.
ScreenShot of the form
//Global Variables
List<Int32> NumberOfSteps = new List<Int32>();
List<Int32> NumberOfDegrees = new List<Int32>();
List<Int32> GlideXPos = new List<Int32>();
List<Int32> GlideYPos = new List<Int32>();
List<String> SayList = new List<String>();
List<String> SoundList = new List<String>();
List<Action> queue = new List<Action>();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void textBox7_TextChanged(object sender, EventArgs e)
{
}
private static Bitmap RotateImageByAngle(Image oldBitmap, float angle)
{
var newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height);
var graphics = Graphics.FromImage(newBitmap);
graphics.TranslateTransform((float)oldBitmap.Width / 2, (float)oldBitmap.Height / 2);
graphics.RotateTransform(angle);
graphics.TranslateTransform(-(float)oldBitmap.Width / 2, -(float)oldBitmap.Height / 2);
graphics.DrawImage(oldBitmap, new Point(0, 0));
return newBitmap;
}
private void button3_Click(object sender, EventArgs e)
{
pictureBox1.Image = RotateImageByAngle(pictureBox1.Image, 30);
}
private void button1_Click(object sender, EventArgs e)
{
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
}
private void HAREKETETTIR(int miktar)
{
deneme2 += miktar;
Point deneme = new Point(deneme2, 455);
pictureBox1.Location = deneme;
}
private void pictureBox1_Click(object sender, EventArgs e)
{
}
private void btnRotate_Click(object sender, EventArgs e)
{
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
}
private void RUN_Click(object sender, EventArgs e)
{
foreach (Action item in queue)
{
item();
}
}
}
When I click Run,The code creates an error as "Input string was not in a correct format."
How can I solve the issue here?
Thanks
Your question does not contain information, which part of program produces error, but it is probably Convert.ToInt32(txtNumberOfSteps.Text).
First reason of error could be that txtNumberOfSteps.Text does not contain text convertible to integer, so make sure user can enter only valid integer or provide appropriate error handling (e.g. check txtNumberOfSteps.Text before you enqueue action and display user some error message).
Second reason is more tricky to spot. If you add Action to queue like this
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(txtNumberOfSteps.Text)); });
then method Convert.ToInt32() would try to convert value of txtNumberOfSteps.Text as it is in the moment you run the action, not as it was when you queued the action. So for example if user queues one action when txtNumberOfSteps.Text contains "2" and then he changes txtNumberOfSteps.Text to empty string and run actions in queue, you would received error, because empty string is not valid integer. This can be easily fixed by creating temporary variable containing copy of value in txtNumberOfSteps.Text in the moment of enqueing the action.
private void button1_Click(object sender, EventArgs e)
{
var text = txtNumberOfSteps.Text;
queue.Add(() => { HAREKETETTIR(Convert.ToInt32(text)); });
}
(and the same problem is in btnRotate_Click() method).
You can read about this problem in more detail here.
It looks to me like your error is because txtNumberOfSteps.Text is actually an invalid number. You are adding the actions to your queue correctly, and running them correctly as far as I can see.
This question already has answers here:
How do I update the GUI from another thread?
(47 answers)
Closed 8 years ago.
I am using UI with multiple buttons and I need to start background task on button click and report back to main thread + update UI when the task is finished.
This is currently part of my code:
private void button1Click(object sender, EventArgs e)
{
button1.Text = "Starting";
button1.Enabled = false;
button1Worker.RunWorkerAsync();
}
private void button1worker_DoWork(object sender, DoWorkEventArgs e)
{
toolStarter.startTool("button1");
}
private void button1worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
button1.Text = "Autoruns";
button1.Enabled = true;
}
This solution works as intended / expected, however the same code is repeated for 15 different buttons and that seem to be wrong to me.
Can you recommend some other way to do the same thing?
I did try ThreadPool queue but did not manage to update UI after task finished.
You can do this via async/await instead, which simplifies the code and eliminates the need for the background worker(s):
private async void button1Click(object sender, EventArgs e)
{
button1.Text = "Starting";
button1.Enabled = false;
await Task.Run(() => toolStarter.startTool("button1"));
button1.Text = "Autoruns";
button1.Enabled = true;
}
If your buttons are all doing the same operation, with only the string changing, you can refactor this out to support that:
private async Task ExecuteButton(Button button, string toolName)
{
button.Text = "Starting";
button.Enabled = false;
await Task.Run(() => toolStarter.startTool(toolName));
button.Text = "Autoruns";
button.Enabled = true;
}
private async void button1Click(object sender, EventArgs e)
{
await ExecuteButton(button1, "button1");
// Do any other specific stuff for after here
}
// Use for other buttons as needed
private async void button2Click(object sender, EventArgs e)
{
await ExecuteButton(button2, "button2");
}
// This is your helper class that actually does the work
public class ToolStarter
{
public void startTool(string name)
{
// Put your switch statement here to decide what work to do
}
}
public class ButtonWorker
{
private Button button;
private ToolStarter toolStarter;
public ButtonWorker(Button button, ToolStarter toolStarter)
{
this.button = button;
this.toolStarter = toolStarter;
this.button.Enabled = false;
this.button.Text = "Starting";
ThreadPool.QueueUserWorkItem(new WaitCallback(DoWork));
}
private void DoWork(object state)
{
this.toolStarter.startTool(button.Name);
// Pass control back to the UI thread so you can update your
// button text and enabled/status
this.button.Invoke(new Action(() =>
{
this.button.Text = "Autoruns";
this.button.Enabled = true;
}));
}
}
// This is just showing you how to use the ButtonWorker
public class ButtonWorkerTest
{
public ButtonWorkerTest()
{
var btn1 = new Button { Name = "button1" };
var btn2 = new Button { Name = "button2" };
var toolstarter = new ToolStarter(); // This is your class
var worker1 = new ButtonWorker(btn1, toolstarter);
var worker2 = new ButtonWorker(btn2, toolstarter);
}
}
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.