如何在 windows 表单应用程序中同时 运行 两项任务?
How can I run two tasks at once in windows forms app?
我想寻求有关一些小型 C# 项目的帮助。我有一个 windows 表单应用程序,其目的是编写用户输入的文本。它基本上由一个文本框和一个按钮组成。当您按下按钮时,程序获取文本并跳入循环,在循环中它总是只获取一个符号并使用 SendKeys.Send() 发送它。这没有任何问题,但最近我想添加一个功能,它允许我通过按键停止程序。我被困在这一点上,因为程序在“写入”循环中 运行。我唯一的想法是检查循环内的按键,但除了 KeyPress 事件,我找不到任何其他注册按键的方法。有人知道吗??
我的代码:
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
String textToWrite;
int delay;
bool continueWriting = true;
enum KeyModifier
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
WinKey = 8
}
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
int id = 0;
RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode());
}
private void pisBut_Click(object sender, EventArgs e)
{
textToWrite= textToWriteTextBox.Text;
Console.WriteLine(zadaniText);
continueWriting = true;
Thread.Sleep(5000);
try
{
delay = Convert.ToInt32(delayBetweenSymbolsTextBox.Text);
}
catch
{
Console.WriteLine("conversion failed!");
}
for (int i = 0; i < textToWrite.Length; i++)
{
// loop intended to take one char and send it
Random nahoda = new Random();
SendKeys.Send(zadaniText[i].ToString());
int finalDelay = nahoda.Next(delay - 40, delay);
Console.WriteLine(finalDelay);
Thread.Sleep(finalDelay);
if (continueWriting == false) // stop after setting this bool false
{
break;
}
}
}
private void zadani_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// interrupt writing
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);
int id = m.WParam.ToInt32(); .
MessageBox.Show("Hotkey has been pressed!");
continueWriting = false;
}
}
private void ExampleForm_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 0);
}
}
谢谢!!
您的问题可能与 UI 线程被重复调用 Thread.Sleep
阻塞有关,使得 UI non-responsive。解决此问题的一种简单方法是使 Click
事件的处理程序异步(添加 async
修饰符),并将 Thread.Sleep
替换为 await Task.Delay
。这样 UI 将在发送密钥的整个操作期间保持响应。
private async void Button_Click(object sender, EventArgs e)
{
//...
await Task.Delay(5000); // Instead of Thread.Sleep(5000);
//...
}
这可能会产生另一个问题,即当 send-keys 操作正在进行时用户将能够再次单击该按钮,但我相信您会找到解决此问题的方法。
我会考虑使用 Microsoft 的 Reactive Framework(又名 Rx)- NuGet System.Reactive.Windows.Forms
并添加 using System.Reactive.Linq;
- 然后您可以这样做:
private IDisposable _subscription = null;
private void pisBut_Click(object sender, EventArgs e)
{
if (int.TryParse(delayBetweenSymbolsTextBox.Text, out delay))
{
Random random = new Random();
_subscription =
Observable
.Generate(
0, x => x < zadaniText.Length, x => x + 1, x => x,
x => TimeSpan.FromMilliseconds(x == 0 ? 5000.0 : random.Next(delay - 40, delay)))
.ObserveOn(this)
.Subscribe(i => SendKeys.Send(zadaniText[i].ToString()));
}
}
现在要中途停止发送密钥,您可以这样做:_subscription?.Dispose();
。
我想寻求有关一些小型 C# 项目的帮助。我有一个 windows 表单应用程序,其目的是编写用户输入的文本。它基本上由一个文本框和一个按钮组成。当您按下按钮时,程序获取文本并跳入循环,在循环中它总是只获取一个符号并使用 SendKeys.Send() 发送它。这没有任何问题,但最近我想添加一个功能,它允许我通过按键停止程序。我被困在这一点上,因为程序在“写入”循环中 运行。我唯一的想法是检查循环内的按键,但除了 KeyPress 事件,我找不到任何其他注册按键的方法。有人知道吗??
我的代码:
public partial class Form1 : Form
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool RegisterHotKey(IntPtr hWnd, int id, int fsModifiers, int vk);
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool UnregisterHotKey(IntPtr hWnd, int id);
String textToWrite;
int delay;
bool continueWriting = true;
enum KeyModifier
{
None = 0,
Alt = 1,
Control = 2,
Shift = 4,
WinKey = 8
}
public Form1()
{
InitializeComponent();
this.KeyPreview = true;
int id = 0;
RegisterHotKey(this.Handle, id, (int)KeyModifier.Shift, Keys.A.GetHashCode());
}
private void pisBut_Click(object sender, EventArgs e)
{
textToWrite= textToWriteTextBox.Text;
Console.WriteLine(zadaniText);
continueWriting = true;
Thread.Sleep(5000);
try
{
delay = Convert.ToInt32(delayBetweenSymbolsTextBox.Text);
}
catch
{
Console.WriteLine("conversion failed!");
}
for (int i = 0; i < textToWrite.Length; i++)
{
// loop intended to take one char and send it
Random nahoda = new Random();
SendKeys.Send(zadaniText[i].ToString());
int finalDelay = nahoda.Next(delay - 40, delay);
Console.WriteLine(finalDelay);
Thread.Sleep(finalDelay);
if (continueWriting == false) // stop after setting this bool false
{
break;
}
}
}
private void zadani_PreviewKeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Enter)
{
// interrupt writing
}
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0x0312)
{
Keys key = (Keys)(((int)m.LParam >> 16) & 0xFFFF);
KeyModifier modifier = (KeyModifier)((int)m.LParam & 0xFFFF);
int id = m.WParam.ToInt32(); .
MessageBox.Show("Hotkey has been pressed!");
continueWriting = false;
}
}
private void ExampleForm_FormClosing(object sender, FormClosingEventArgs e)
{
UnregisterHotKey(this.Handle, 0);
}
}
谢谢!!
您的问题可能与 UI 线程被重复调用 Thread.Sleep
阻塞有关,使得 UI non-responsive。解决此问题的一种简单方法是使 Click
事件的处理程序异步(添加 async
修饰符),并将 Thread.Sleep
替换为 await Task.Delay
。这样 UI 将在发送密钥的整个操作期间保持响应。
private async void Button_Click(object sender, EventArgs e)
{
//...
await Task.Delay(5000); // Instead of Thread.Sleep(5000);
//...
}
这可能会产生另一个问题,即当 send-keys 操作正在进行时用户将能够再次单击该按钮,但我相信您会找到解决此问题的方法。
我会考虑使用 Microsoft 的 Reactive Framework(又名 Rx)- NuGet System.Reactive.Windows.Forms
并添加 using System.Reactive.Linq;
- 然后您可以这样做:
private IDisposable _subscription = null;
private void pisBut_Click(object sender, EventArgs e)
{
if (int.TryParse(delayBetweenSymbolsTextBox.Text, out delay))
{
Random random = new Random();
_subscription =
Observable
.Generate(
0, x => x < zadaniText.Length, x => x + 1, x => x,
x => TimeSpan.FromMilliseconds(x == 0 ? 5000.0 : random.Next(delay - 40, delay)))
.ObserveOn(this)
.Subscribe(i => SendKeys.Send(zadaniText[i].ToString()));
}
}
现在要中途停止发送密钥,您可以这样做:_subscription?.Dispose();
。