gpt4 book ai didi

c# - 如何在单独的线程中执行自定义类的方法调用?

转载 作者:行者123 更新时间:2023-11-30 21:13:09 24 4
gpt4 key购买 nike

我有一个 UI、一个自定义类和一个线程。我想在一个单独的线程中完全运行自定义类。有没有一种干净的方法可以做到这一点?

例如。在下面的 MainForm 上,当 UI 调用 _threadOneClass.Sleep 时,我需要 UI 转到生成的 ThreadOne 并在 ThreadOne 中调用 Sleep 方法,而不是在主线程中。

基本上,MyClass中的所有方法调用都需要在ThreadOne中执行,而不是在主线程中执行。就像 MyClass 在其自己的“进程”上运行,同时仍然可见以从 MainForm 调用。

MainForm 有 3 个按钮和 1 个用于记录的文本框。

本来想派生Thread类,但是是密封的。因此,根据 Microsoft 的说法,推导绝对是错误的方法。

求助各位高手?

这是输出(MainThread ID=10,ThreadOne ID=11)

MyClass instantiatedStarting ThreadOne11-Run.startSleeping ThreadOne10-Run.sleep for 3000    'Need this to run on ThreadID 1110-Run.woke up           'Need this to run on ThreadID 11Stopping ThreadOne11-Run.done

Here is how the code look like.

public partial class MainForm : Form
{
public MainForm()
{
InitializeComponent();
}

private Thread _threadOneThread;
private MyClass _threadOneClass;

private void btnThreadOneCreate_Click(object sender, EventArgs e)
{
_threadOneClass = new MyClass(this);
_threadOneThread = new Thread(new ThreadStart(_threadOneClass.Run));
_threadOneThread.Start();
}

private void btnThreadOneStop_Click(object sender, EventArgs e)
{
_threadOneClass.IsRunning = false;
}

private void btnThreadOneSleep_Click(object sender, EventArgs e)
{
_threadOneClass.Sleep(3000);
}

public void Log(string txt)
{
MainForm.SetText(txtLog, txt);
}

internal static void SetText(Control ctl, string val)
{
if (ctl.InvokeRequired)
ctl.Invoke((MethodInvoker)delegate() { ctl.Text += Environment.NewLine + val; });
else
ctl.Text += Environment.NewLine + val;
}
}

class MyClass
{
public MyClass(MainForm frm)
{
_mainForm = frm;
}
private MainForm _mainForm;
public bool IsRunning = true;
public void Run()
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.start");
while (IsRunning) { }
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.done");
}

public void Sleep(int milliseconds)
{
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.sleep for " + milliseconds.ToString());
Thread.Sleep(milliseconds);
_mainForm.Log(Thread.CurrentThread.ManagedThreadId.ToString() + "-Run.woke up");
}
}

最佳答案

线程允许您在继续做其他事情的同时运行繁重的操作。在用户界面(您的场景)的情况下,异步行为几乎总是必要的,因为阻塞 UI 线程将导致对用户无响应,这不是一种选择。

幸运的是,Microsoft 的人们已经让以异步方式编写相同的代码变得极其容易。我通常使用 Tasks,因为我喜欢你对操作的控制以及 ContinueWith() 允许你控制你对结果的处理,如果你需要将数据传播回调用线程。如果您更喜欢使用线程,ThreadPool.QueueUserWorkItem 也同样简单。

任何你不想阻塞 UI 线程的操作都像这样包装它,

Task.Factory.StartNew(() => Object.PerformOperation());

ThreadPool.QueueUserWorkItem(new WaitCallback((x) => Object.PeroformOperation()));

我发现这让我可以编写完全相同的代码,但不会阻塞 UI 线程。如果您有多个语句要执行,您也可以使用 block 。

Task.Factory.StartNew(() =>
{
// do something
// do more stuff
// done
}).ContinueWith((completedTask) =>
{
// if you were computing a value with the task
// you can now do something with it
// this is like a callback method, but defined inline

// use ui's dispatcher if you need to interact with ui compontents
UI.Label.Dispatcher.Invoke(new Action(() =>
UI.Item.Label.Text = completedTask.Result;
}

即将在下一个 .net 版本中发布的异步功能实际上进一步简化了这一过程!但由于它使用任务,您仍然希望能够轻松地使用它们。

// this will begin the operation, then return control back to the ui so it does not hang. 
var result = await Object.PerformLongTask();

// once the long task is completed then it continues and you can use the result
UI.Item.Label = result;

举一个真实的例子,这是我写的一个 FTP 客户端的一些代码,它有一个 WPF 前端。单击开始按钮时,ftp 传输在其自己的任务中启动,然后在任务中启动每半秒更新一次界面的 while 循环,因此两者都不会干扰界面线程。同样是相同的代码,只是包裹在 lambada 中。

    private void btnStart_Click(object sender, RoutedEventArgs e)
{
Task.Factory.StartNew(() =>
ftp.Mirror(@"C:\LocalFolder", "/RemoteFolder", 10));

Task.Factory.StartNew(() =>
{
while (true)
{
lbPercentSuccess.Dispatcher.Invoke(new Action(() =>
{
lbPercentSuccess.Content = ftp.FtpProgress.SuccessPercentage;
lbPercentError.Content = ftp.FtpProgress.ErrorPercentage;
lbPercentTotal.Content = ftp.FtpProgress.TotalPercentage;
lbDuration.Content = ftp.FtpProgress.Duration;
}));

Thread.Sleep(500);
}
});
}

关于c# - 如何在单独的线程中执行自定义类的方法调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6990356/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com