C ++ CLI后台工作程序运行时错误 [英] C++ CLI Background Worker Runtime Error

查看:80
本文介绍了C ++ CLI后台工作程序运行时错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我似乎遇到了一个问题,我的程序强制出错。

http://puu.sh/mUq0l/600ed167c1.png



我不确定如何修复它,因为我只有C ++标准多线程的经验。



[code]

I seem to be having an issue where my program forces an error.
http://puu.sh/mUq0l/600ed167c1.png

I am not certain to how to fix it as I only have experience with the standard multi threading in C++.

[code]

void setText(int data)
	{
		pingOutbox->Text = Convert::ToString(data);
		pingOutbox->Refresh();
		cout << data << endl;
	}

	void mainPingThing()
	{
		int speed;
		setText(runPing());
		Sleep(2500);
	}

	private: System::Void backgroundWorker1_DoWork_1(System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) 
	{
		while (true) { mainPingThing(); }
	}



[/ code]

这是我所做的基本布局。我不知道必须做出哪些更正。任何帮助都会受到高度赞赏,因为微软的疯狂无所不知。


[/code]
This is the basic layout of what I have done. I do not know what corrections have to be made. Any help would be much appreciated as Microsoft's craziness knows no limits.

推荐答案

很容易将所有罪行归咎于微软,包括你自己的罪。同时,异常消息非常明确,并解释了您的错误:尝试在某些非UI线程中使用某个对象,但此对象是UI的一部分,并在UI线程中创建并添加到UI。这是无效的操作。所有这些操作都应该在UI线程中完成。你可以在非UI线程中使用它们吗?当然可以。



你不能从非UI线程中调用与UI相关的任何内容。相反,您需要使用 Invoke System.Windows.Threading的方法。 Dispatcher (对于Forms或WPF)或 System.Windows.Forms.Control (仅限表单)。



您将在我过去的答案中找到有关其工作原理和代码示例的详细说明:

Control.Invoke()与Control.BeginInvoke()

使用Treeview扫描仪和MD5的问题



另请参阅有关线程的更多参考资料:

主要的.NET事件线程

如何让keydown事件在不同的线程上运行i n vb.net

启用禁用+多线程后控制事件不会触发







上面描述的机制在 System.Windows.Forms 和WPF UI中都是通用的,可以在任何线程中使用。但是我忘了提到特定于 System.ComponentModel.BackgroundWorker 的机制。 Philippe Mori在他对此解决方案的评论中提醒我:

BackgroundWorker.ReportProgress方法(System.ComponentModel) [ ^ ],

BackgroundWorker.ProgressChanged事件(System.ComponentModel) [ ^ ]。



基本上,您可以在任何线程中直接调用 System.ComponentModel.BackgroundWorker.ReportProgress 。此调用是从任何类型的UI中抽象出来的。如果处理事件 System.ComponentModel.BackgroundWorker.ProgressChanged ,则会发生UI线程的委派。这是以UI特定的方式完成的;当然,在事件处理程序中,您可以直接处理UI元素。



-SA
It's way to easy to blame Microsoft in all sins, including your own. At the same time, the exception message is crystal clear and explains what you did wrong: tried to works with some object in some non-UI thread, but this object is part of UI and was created and added to UI in a UI thread. This is invalid operation. All such operations should be done in a UI thread. Can you work with them in a non-UI thread? Of course you can.

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke(),
Problem with Treeview Scanner And MD5.

See also more references on threading:
.NET event on main thread,
How to get a keydown event to operate on a different thread in vb.net,
Control events not firing after enable disable + multithreading.



The mechanism I described above is universal in both System.Windows.Forms and WPF UI and can be used in any thread. But I forgot to mention the mechanism specific to System.ComponentModel.BackgroundWorker. Philippe Mori reminded me about it in his comment to this solution:
BackgroundWorker.ReportProgress Method (System.ComponentModel)[^],
BackgroundWorker.ProgressChanged Event (System.ComponentModel)[^].

Basically, you can directly call System.ComponentModel.BackgroundWorker.ReportProgress in any thread. This call is abstracted from any kind of UI. The delegation to the UI thread happens if you handle the event System.ComponentModel.BackgroundWorker.ProgressChanged; and this is done in a UI-specific way; naturally, in the event handler, you can address UI elements directly.

—SA


由于您已经在使用后台工作程序,解决问题的最简单方法是正确使用它!



As you are already using a background worker, the easiest way to fix the problem would be to use it properly!

private: System::Void backgroundWorker1_DoWork_1(
    System::Object^  sender, System::ComponentModel::DoWorkEventArgs^  e) 
{
    while (true)
    {
        int data = runPing();
        backgroundWorker1->ReportProgress(0, Convert::ToString(data));
        Sleep(2500);
    }
}





并为ProgressChanged事件连接一个处理程序,然后将一些代码移到它:



And connect an handler for ProgressChanged event and then move some of your code to it:

void backgroundWorker1_ProgressChanged(object sender,
    ProgressChangedEventArgs e)
{
    // I forgotten to change a . to ->. In C++/cli, you use the arrows for members 
    // while in C#, it is the dot.
    auto textData = e->UserData.ToString()UserState->ToString();
    pingOutbox->Text = textData;

    // Not necessary. The UI will update itself if the main thread is responding.
    // pingOutbox->Refresh();    

    cout << textData << endl;
}





也许有可能在背景循环中留下cout但是如果输出文本可能会搞乱多个线程正在写入它。



更新

顺便说一句,阅读官方文档会有所帮助:< a href =https://msdn.microsoft.com/en-us/library/waw3xexc(v=vs.110).aspx>如何:实现使用后台操作的表单 [ ^ ]



此外,一旦您收到错误消息,使用Google搜索帮助非常容易,您无需等待某人回答!



It would probably also be possible to leave cout in the background loop but it might mess up the outputed text if multiple threads are writing to it.

Update
By the way, reading official documentation would help: How to: Implement a Form That Uses a Background Operation[^]

Also, it is very easy to search help using Google once you have the error message and you won't have to wait for someone to answer!


这篇关于C ++ CLI后台工作程序运行时错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆