C++后端和C#前端?

13

我有一个项目,需要每秒处理数百,甚至数千条信息,并相应地在图表上处理/绘制这些数据。(用户将搜索一组数据,在实时绘制图表,而不是在图表上绘制数千个值)

我对使用DLL在C++中进行大量消息处理,然后将信息传递到C#界面方面感到困惑。有人可以为我解释一下吗?

此外,由于速度是重点,我想知道在两个不同层的代码之间进行访问是否会比完全使用C#或C++编写项目具有更大的性能损失。但是,我读到了关于在C++中编程GUI的不好的事情;关于这一点,这个应用程序必须看起来现代,干净,专业等。所以我认为C#可能是未来的发展方向(也许是XAML、WPF)。

谢谢你的时间。


7
几千条消息并不算太多。除非它们非常复杂,否则C#也应该可以处理它们。 而且C++提供了不错的GUI库(QT被认为还可以)。 因此我认为这三种解决方案都可能可行。 - CodesInChaos
抱歉,我刚看到你的评论。干杯:D 我不确定在任何时候发送1000-2000条消息是否很多。我在下面发布了这个:“实际上,我将接收每个消息并解析它,以人类可读的形式存储它,然后在GUI中显示它。就我所见,解析和存储将持续发生,而GUI的某些元素(例如图表、表格)将按需显示(查询数据/用户交互)。”有什么想法吗?再次感谢您的帮助! - Sparky
“Parsing”是什么意思?它有多复杂?以及将其以人类可读的形式存储有多复杂? - Vilx-
抱歉,我的意思是数据一开始可能无法读取,但我需要对每个消息应用转换,以便以易于阅读的方式存储并输出到屏幕上进行阅读。例如,如果我从交易所获取数据,我希望将其存储,以便用户可以轻松地查看最佳买入/卖出价和其他相关信息。这样清楚了吗? - Sparky
老实说,我不理解这个讨论……你是担心如果用C#编写数据转换会很慢吗(在你尝试之前)? - Paul Michalik
嗯,我想我只是希望能够就从一开始应该使用哪种语言做出明智的决定。我不想使用C#发现它不够快,虽然现在我知道这很荒谬,因为最终关键在于我如何优化我的代码。不管怎样,感谢大家的帮助。我想我会全部用C#来完成,我很喜欢xaml/wpf所带来的强大GUI功能,而且我对它很熟悉。 - Sparky
5个回答

11

在C/C++ DLL和.NET Assembly之间进行互操作的最简单方法是通过p/invoke。在C/C++方面,您可以像创建其他任何DLL一样创建一个DLL。在C#方面,您需要创建一个p/invoke声明。例如,假设您的DLL是mydll.dll并且导出一个方法void Foo()

[DllImport("mydll.dll")]
extern static void Foo();
那就这样了。你只需像调用其他静态类方法一样调用Foo即可。难点在于数据编组,这是一个复杂的主题。如果你正在编写DLL,你可以努力让导出函数易于编组。有关P/invoke数据编组的更多信息,请参见此处:http://msdn.microsoft.com/en-us/magazine/cc164123.aspx
使用P/invoke时,性能会受到影响。每当托管应用程序调用未托管方法时,它都需要跨越托管/未托管边界,并再次返回。在编组数据时,会进行大量的复制。如果需要,可以通过使用“不安全”的C#代码(使用指针直接访问未托管内存)来减少复制。
你应该知道的是,所有.NET应用程序都充满了P/invoke调用。没有.NET应用程序可以避免发出操作系统调用,每个操作系统调用都必须跨越进入操作系统的未托管世界。WinForms甚至WPF GUI应用程序每秒钟都要进行数百甚至数千次的跨越。
如果这是我的任务,我首先会完全使用C#完成。然后,我会对其进行分析和优化。

1
哪种更简单还有争议,但是通过将/clr传递给Visual C++编译器的C++互操作性肯定比p/invoke更快。 - Ben Voigt
我觉得我开始倾向于选择C#选项。我应该提到,在这之前我实际上必须要学习C++,而我已经了解了C#。我一直在阅读关于C++只有在人们精通优化时才会更快的文章,而对于刚接触C++的我来说,这绝对不是这种情况。感谢您的帮助。 - Sparky

7
如果速度是您的首要任务,那么C++可能是更好的选择。尝试估计计算的难度(如果每个消息的计算很容易,那么处理1000条消息在C#中可能很简单,但即使是最优化的程序也可能太难)。如果您的算法复杂,涉及不同的类等,则C++可能具有更多优势(关于性能)。
您可能想看一下这个问题的性能比较
将后端和前端分开是个好主意。是否会因为一个使用C++而另一个使用C#而获得性能惩罚,取决于实际需要多少数据转换。
我认为编程GUI通常并不痛苦。MFC可能很痛苦,但Qt不会(依我之见)。
也许这些内容可以给您一些启示!

4

另一种可能的解决方案:听起来这个任务非常适合并行处理。以这样的方式构建您的应用程序,使其可以将工作负载分配到多个 CPU 核心甚至不同的机器上。然后,您可以通过增加硬件来解决性能问题(如果有的话)。


这实际上是一个非常好的想法,我从未想过。我需要进行一些研究,但感谢这个想法! - Sparky
1
@Sparky - 不要犹豫,用一个赞来表达你的感激之情吧!;) - Vilx-
我还不能点赞 :( 我已经在上面说过了...等我可以的时候我会点赞的。 - Sparky
1
@Sparky - 你被授予了投票的能力,无论是对问题、答案还是评论。明智地使用它吧! - Vilx-

3
如果你有C/C++源代码,请考虑将其链接到C++/CLI .NET程序集中。这种项目允许您混合非托管代码并将托管接口放在其上。结果是一个简单的.NET程序集,可以轻松在C#或VB.NET项目中使用。
简单类型具有内置的马歇兰,因此您可以从托管C++侧调用未管理的一侧的函数。
唯一需要注意的是,当您将委托封送为函数指针时,它不持有引用,因此如果您需要C++保留托管回调,则需要安排保留引用。除此之外,大多数内置转换按预期工作。Visual Studio甚至会让您跨界调试(打开非托管调试)。
如果您有.lib文件,则可以在C++/CLI项目中使用它,只要它动态链接到C运行时即可。

1

在你开始忙着将数据编组和解组成不安全结构,以便能调用 C++ DLL 中的函数之前,最好先在 C# 中原型化一下。C# 往往比你想象的要快。原型开发成本较低。


1
我实在没有时间去原型化它,因为这将是我的毕业项目,但我想我会选择完全用C#进行编程。干杯 :) - Sparky
好的,但是关于原型设计的一个重要点是它不需要花费很长时间。这也是一个快速达到弗雷德布鲁克斯所说的“建立一个用来扔掉的”目标的方法。 - Robert Rossney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接