[英]My Emergency Stop button doesn't work because the code is running and the UI won't respond
我正在控制 SCARA 機器人的短臂順時針和逆時針旋轉。 現在我想創建一個緊急停止裝置,它可以在機器人即將撞牆時停止它的短鏈接。 但我現在面臨的問題是,在移動短鏈接時,無法單擊表單上的任何按鈕。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace SerialPort
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
cmdClose.Enabled = false;
LongArmClose.Enabled = false;
foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
{
txtPort.Items.Add(s);
}
foreach (String s in System.IO.Ports.SerialPort.GetPortNames())
{
LongArmPort.Items.Add(s);
}
}
public System.IO.Ports.SerialPort shortPort;
public System.IO.Ports.SerialPort LongPort;
public void shortSerialPort_connect(String port, int baudrate, Parity parity, int databits, StopBits stopbits)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
shortPort = new System.IO.Ports.SerialPort(
port, baudrate, parity, databits, stopbits);
try
{
shortPort.Open();
cmdClose.Enabled = true;
cmdConnect.Enabled = false;
txtReceive.AppendText("[" + dtn + "] " + "Short Link Port Connected\n");
shortPort.DataReceived += new SerialDataReceivedEventHandler(shortPort_DataReceived);
ShortInitializationCommand();
}
catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
}
public void LongSerialPort_connect(String port, int baudrate, Parity parity, int databits, StopBits stopbits)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
LongPort = new System.IO.Ports.SerialPort(
port, baudrate, parity, databits, stopbits);
try
{
LongPort.Open();
LongArmClose.Enabled = true;
LongArmConnect.Enabled = false;
LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link Port Connected\n");
LongPort.DataReceived += new SerialDataReceivedEventHandler(LongPort_DataReceived);
LongInitializationCommand();
}
catch (Exception ex) { MessageBox.Show(ex.ToString(), "Error"); }
}
private void ShortInitializationCommand()
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String[] commands = new String [14];
commands[0] = "^KP 1 10"; // Set proportional gain
commands[1] = "^KI 1 0"; // Set integral gain
commands[2] = "^KD 1 0"; // Set differential gain
commands[3] = "^ALIM 1 33"; // Set Amps limit
commands[4] = "^ATRIG 1 30";// Set Amps Trigger level
commands[5] = "^ATGA 1 17"; // Set Amps Trigger action
commands[6] = "^EMOD 1 18"; // Encoder 1 as feedback for channel 1
commands[7] = "^EHL 1 4096";// Set max counter limit for Encoder 1
commands[8] = "^ELL 1 -4096";//Set min counter limit for Encoder 1
commands[9] = "^EHLA 1 17"; // Set high limit action as safethy stop for Encoder 1
commands[10] = "^ELLA 1 17";// set low limit action as safety stop for Encoder 1
commands[11] = "^EPPR 1 2048";//Set up pulses per revolution for encoder 1
commands[12] = "^MMOD 1 3";// set to closed loop count position
commands[13] = "^MXRPM 1 1";// set speed/ accelevation limit
for (int i = 0; i <14; i++)
{
String data = commands[i] + '\r';
shortPort.Write(data);
txtReceive.AppendText("[" + dtn + "] " + "Short Link Sent: " + data + "\n");
}
txtReceive.AppendText("[" + dtn + "] " + "Short Link initialization finished " + "\n");
}
private void LongInitializationCommand()
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String[] commands = new String[14];
commands[0] = "^KP 1 10"; // Set proportional gain
commands[1] = "^KI 1 0"; // Set integral gain
commands[2] = "^KD 1 0"; // Set differential gain
commands[3] = "^ALIM 1 33"; // Set Amps limit
commands[4] = "^ATRIG 1 30";// Set Amps Trigger level
commands[5] = "^ATGA 1 17"; // Set Amps Trigger action
commands[6] = "^EMOD 1 18"; // Encoder 1 as feedback for channel 1
commands[7] = "^EHL 1 4096";// Set max counter limit for Encoder 1
commands[8] = "^ELL 1 -4096";//Set min counter limit for Encoder 1
commands[9] = "^EHLA 1 17"; // Set high limit action as safethy stop for Encoder 1
commands[10] = "^ELLA 1 17";// set low limit action as safety stop for Encoder 1
commands[11] = "^EPPR 1 2048";//Set up pulses per revolution for encoder 1
commands[12] = "^MMOD 1 3";// set to closed loop count position
commands[13] = "^MXRPM 1 1";// set speed/ acc elevation limit
for (int i = 0; i < 14; i++)
{
String data = commands[i] + '\r';
LongPort.Write(data);
LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link Sent: " + data + "\n");
}
LongLinkReceived.AppendText("[" + dtn + "] " + "Long Link initialization finished " + "\n");
}
private void shortPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
txtReceive.AppendText("[" + dtn + "] " + "Received: " + shortPort.ReadExisting() + "\n");
}));
}
private void LongPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
this.BeginInvoke(new Action(() =>
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
LongLinkReceived.AppendText("[" + dtn + "] " + "Received: " + LongPort.ReadExisting() + "\n");
}));
}
private void cmdConnect_Click(object sender, EventArgs e)
{
String port = txtPort.Text;
int baudrate = Convert.ToInt32("115200");
Parity parity = (Parity)Enum.Parse(typeof(Parity), "None");
int databits = Convert.ToInt32("8");
StopBits stopbits = (StopBits)Enum.Parse(typeof(StopBits), "One");
shortSerialPort_connect(port, baudrate, parity, databits, stopbits);
}
private void LongArmConnect_Click(object sender, EventArgs e)
{
String port = LongArmPort.Text;
int baudrate = Convert.ToInt32("115200");
Parity parity = (Parity)Enum.Parse(typeof(Parity), "None");
int databits = Convert.ToInt32("8");
StopBits stopbits = (StopBits)Enum.Parse(typeof(StopBits), "One");
LongSerialPort_connect(port, baudrate, parity, databits, stopbits);
}
private void Send_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String data = txtDatatoSend.Text + '\r';
shortPort.Write(data);
txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
}
private void LongArmSend_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String data = LongArmCommand.Text + '\r';
LongPort.Write(data);
LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
}
private void cmdClose_Click_1(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
if (shortPort.IsOpen)
{
shortPort.Close();
cmdClose.Enabled = false;
cmdConnect.Enabled = true;
txtReceive.AppendText("[" + dtn + "] " + "Disconnected\n");
}
}
private void LongArmClose_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
if (LongPort.IsOpen)
{
LongPort.Close();
LongArmClose.Enabled = false;
LongArmConnect.Enabled = true;
LongLinkReceived.AppendText("[" + dtn + "] " + "Disconnected\n");
}
}
private void ShortLinkClockwise_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String angle_string = ShortLinkAngle.Text;
double angle = Convert.ToDouble(angle_string);
int Encoder = Convert.ToInt32(angle * 22.76);
String Encoder_string = Encoder.ToString();
String data = "!PR 1 " + Encoder_string + '\r';
shortPort.Write(data);
txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
//WHEN IT REACHES THE EXTREM, IT CANNOT BOUNCE BACK. SHOULD THERE BE ANY MORE SETTING FOR IT
}
private void ShortLinkCounterClockwise_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String angle_string = ShortLinkAngle.Text;
double angle = Convert.ToDouble(angle_string);
angle = angle * -1;
int Encoder = Convert.ToInt32(angle * 22.76);
String Encoder_string = Encoder.ToString();
String data = "!PR 1 " + Encoder_string + '\r';
shortPort.Write(data);
txtReceive.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
}
private void LongLinkClockWise_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String angle_string = LongLinkAngle.Text;
double angle = Convert.ToDouble(angle_string);
int Encoder = Convert.ToInt32(angle * -22.76);
String Encoder_string = Encoder.ToString();
String data = "!PR 1 " + Encoder_string + '\r';
LongPort.Write(data);
LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
//DateTime dt = DateTime.Now;
//String dtn = dt.ToShortTimeString();
//String angle_string = LongLinkAngle.Text;
//double angle = Convert.ToDouble(angle_string);
//int encoder = Convert.ToInt32(-10 * 22.76);
//String encoder_string = encoder.ToString();
//String data = "!PR 1 " + encoder_string + '\r';
//while (angle > 10)
//{
// encoder = Convert.ToInt32(-10 * 22.76);
// encoder_string = encoder.ToString();
// data = "!PR 1 " + encoder_string + '\r';
// LongPort.Write(data);
// angle = angle - 10;
// Thread.Sleep(5000);
//}
//encoder = Convert.ToInt32(angle * -22.76);
//encoder_string = encoder.ToString();
//data = "!PR 1 " + encoder_string + '\r';
//LongPort.Write(data);
//LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
//WHEN IT REACHES THE EXTREM, IT CANNOT BOUNCE BACK. SHOULD THERE BE ANY MORE SETTING FOR IT
}
private void LongLinkCounterClockwise_Click(object sender, EventArgs e)
{
DateTime dt = DateTime.Now;
String dtn = dt.ToShortTimeString();
String angle_string = LongLinkAngle.Text;
double angle = Convert.ToDouble(angle_string);
int Encoder = Convert.ToInt32(angle * 22.76);
String Encoder_string = Encoder.ToString();
String data = "!PR 1 " + Encoder_string + '\r';
LongPort.Write(data);
LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
//DateTime dt = DateTime.Now;
//String dtn = dt.ToShortTimeString();
//String angle_string = LongLinkAngle.Text;
//double angle = Convert.ToDouble(angle_string);
//int encoder = Convert.ToInt32(-10 * 22.76);
//String encoder_string = encoder.ToString();
//String data = "!PR 1 " + encoder_string + '\r';
//while (angle > 10)
//{
// encoder = Convert.ToInt32(10 * 22.76);
// encoder_string = encoder.ToString();
// data = "!PR 1 " + encoder_string + '\r';
// LongPort.Write(data);
// angle = angle - 10;
// Thread.Sleep(5000);
//}
//encoder = Convert.ToInt32(angle * 22.76);
//encoder_string = encoder.ToString();
//data = "!PR 1 " + encoder_string + '\r';
//LongPort.Write(data);
//LongLinkReceived.AppendText("[" + dtn + "] " + "Sent: " + data + "\n");
}
}
}
您應該從 UI 線程中移除長時間運行的任務。 我推薦 BackgroundWorker 類。
http://www.dotnetperls.com/backgroundworker
按照上面的教程,當您准備好后,通過 BackgroundWorker 執行導致您的 ui 凍結的“問題”代碼。
這是一個停車標志,我可以用一點谷歌、筆、紙、幾何圖形和勇氣來制作:
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
namespace CustomButton
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Point[] pts =
{
new Point(40, 40),
new Point(70, 40),
new Point(100, 70),
new Point(100, 100),
new Point(70, 130),
new Point(40, 130),
new Point(10, 100),
new Point(10, 70)
};
GraphicsPath polygon_path = new GraphicsPath(FillMode.Winding);
polygon_path.AddPolygon(pts);
Region polygon_region = new Region(polygon_path);
button1.Region = polygon_region;
button1.Padding = new Padding(5, 35, 0, 0);
button1.SetBounds(button1.Location.X, button1.Location.Y, pts[3].X + 5, pts[4].Y + 5);
button1.BackColor = Color.Red;
button1.ForeColor = Color.White;
button1.TextAlign = ContentAlignment.MiddleCenter;
button1.UseCompatibleTextRendering = true;
button1.Text = "Stop";
}
}
}
為了讓這個按鈕真正取消任何東西,你應該首先將后台工作人員的“WorkerSupportsCancellation”屬性設置為true。
然后,如果 backgroundworker.CancellationPending 屬性為 true,則定期檢查您的 DoWork 函數,並在正確時正確中止操作。
在您的緊急停止點擊事件中,執行以下操作:
// Cancel the asynchronous operation.
this.backgroundWorker1.CancelAsync();
// Disable the Cancel button.
cancelAsyncButton.Enabled = false;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.