Mono准备好迎接黄金时间了吗?[关闭]


314

是否有人在大型或中型项目上使用过开源的.NET实现Mono?我想知道它是否已准备好用于现实世界的生产环境。它稳定,快速,兼容...足以使用吗?将项目移植到Mono运行时是否需要花费很多精力,或者是否真的,真的足够兼容以仅接受并运行Microsoft的运行时已编写的代码?


17
Mindtouch.com在Debian上的Mono上使用C#作为一个非常强大的Wiki平台。去看看他们。您甚至可以下载可以轻松设置和使用的预配置VM。
lamcro

7
我发现mono的最佳用途是可以说:“如果Microsoft做XXX,我们可以在unix上迁移到mono ...”
Ian Ringrose

5
考虑到此问题以来发生的所有变化,我认为这个问题值得重新提出。
Jwosty 2014年

Answers:


402

有两种情况需要考虑:(a)是否要移植现有的应用程序,并且想知道Mono是否足以胜任此任务;(b)您正在开始编写一些新代码,并且想知道Mono是否足够成熟。

对于第一种情况,您可以使用Mono迁移分析器工具(Moma)评估您的应用程序在Mono上的运行距离。如果评估结果令人满意,则应开始进行测试和质量检查,并准备发货。

如果评估返回的报告突出显示了Mono中缺少的功能或语义上有明显不同的功能,则您将必须评估代码是否可以改编,重写或在最坏的情况下您的应用程序是否可以使用简化的功能。

根据我们根据用户提交的Moma统计数据(来自内存),大约50%的应用程序是开箱即用的,大约25%的应用程序需要大约一周的时间(重构,调整),另外15%的应用程序需要认真执行重做您的代码块,其余部分不值得移植,因为它们与Win32紧密地捆绑在一起。到那时,要么从零开始,要么业务决策将推动使代码可移植的工作,但是我们正在谈论几个月的工作(至少从我们的报告中)。

如果您从头开始,则情况会简单得多,因为您将只使用Mono中提供的API。只要您使用受支持的堆栈(几乎是.NET 2.0,再加上3.5中的所有核心升级,包括LINQ和System.Core,再加上任何Mono跨平台API),就可以了。

有时您可能会遇到Mono或bug的错误,并且可能必须解决它们,但这与任何其他系统没有什么不同。

关于可移植性:ASP.NET应用程序更易于移植,因为它们对Win32几乎没有依赖,甚至可以使用SQL Server或其他流行的数据库(Mono捆绑了很多数据库提供程序)。

Windows.Forms的移植有时会比较棘手,因为开发人员喜欢逃脱.NET沙箱,并动动脑筋来配置某些东西,就像更改光标闪烁率(用wParam中以BCD形式编码的两个贝塞尔点表示)一样有用。或像这样的一些垃圾。


276
这个家伙以为他是谁?单声道的创造者??? !! ... o等待..

15
@Drahcir:LINQ适用于Mono。它不是Windows特定的。因此,继续尝试Linux。
2009年

31
“与更改光标闪烁率一样有用的东西,它以wParam中BCD形式编码的两个贝塞尔点表示。”大声笑
usr 2009年

12
非常感谢Mono ...
Evan Plaice 2010年

28
miguel,很高兴收到此帖子的最新消息;-)
David Schmitt

65

它涵盖了.NET 4.0甚至包括.NET 4.5 API的某些功能,但是由于不推荐使用API​​,创建了新的替代方案或范围太广,我们选择了一些未实现的领域大。以下API在Mono中不可用:

  • Windows Presentation Foundation
  • Windows Workflow Foundation(两个版本均未提供)
  • 实体框架
  • WSE1 / WSE2“附加组件”到标准Web服务堆栈

此外,我们的WCF实现仅限于Silverlight支持的功能。

检查特定项目的最简单方法是运行Mono Migration Analyzer(MoMA)。好处是它将通知Mono团队有关问题的信息,这将阻止您使用Mono(如果有),从而使他们可以优先处理工作。

我最近在SubSonic上运行MoMA,发现只有一个问题-Nullable类型的怪异用法。那是一个很大的代码库,因此那里的覆盖范围非常令人印象深刻。

Mono在几种商业以及开源产品中得到了积极的应用。它已在Wikipedia和Mozilla开发人员中心等某些大型应用程序中使用,并已在Sansa MP3播放器等嵌入式应用程序中使用,并为成千上万的已发布游戏提供支持。

在语言级别,Mono编译器完全符合C#5.0语言规范


39

在桌面方面,如果您承诺使用GTK#,Mono可以很好地工作。Windows.Forms的实现仍然存在一些问题(例如,TrayIcon不能正常工作),但是它已经走了很长一段路。此外,GTK#确实比Windows Forms更好。

在网络方面,Mono已经实现了足够的ASP.NET,可以完美地运行大多数站点。此处的困难是找到在Apache上安装了mod_mono的主机,或者,如果您具有对主机的shell访问权限,请自己完成。

无论哪种方式,Mono都很棒且稳定。

创建跨平台程序时要记住的关键事项:

  • 使用GTK#代替Windows.Forms
  • 确保正确区分您的文件名
  • 使用Path.Separator而不是硬编码"\",也使用Environment.NewLine而不是"\n"
  • 不要对Win32 API使用任何P /已调用的调用。
  • 不要使用Windows注册表。

2
Path.Separator是一个很好的建议,但OS X上的Mono具有':'而不是'/'!哈!那是旧的Mac OS(<= 9.0)分隔符。ha?Unix一直都是。
Jared Updike 2010年

3
我不必理会Environment.NewLine或Path.Separator,只需使用/和\ n。当前普遍使用的每个桌面系统(除非我缺少一些)都使用/和\ n。Windows更喜欢\和\ r \ n,但是会很乐意使用unix。
Programmdude

23

我个人在黄金时段使用Mono。我运行的Mono服务器处理的是千兆字节的udp / tcp数据处理相关任务,因此无法满足要求。

有一些特殊性,最烦人的事情之一是,由于Mono的当前状态,您不能仅“构建” msbuild文件:

  • MonoDevelop(IDE)有部分msbuild支持,但是除了简单的hello-world(自定义生成任务,诸如$(SolutionDir)之类的动态“属性”,实际配置,仅举几例)之外,基本上都会在任何“ REAL”构建conf上都陷入困境-完)
  • xbuild 应该是由单机提供的msbuild-完全兼容-build -system甚至更可怕,因此从命令行进行构建实际上比使用GUI更糟糕,这是GUI的非常“非常规”状态。 Linux环境联盟...

一旦/在实际构建东西的过程中,即使对于应该支持的代码,您也可能会看到一些荒唐之处,例如:

  • 编译器对某些构造感到厌烦
  • 以及某些更高级/新的.NET类向您抛出意外的废话(XLinq有人吗?)
  • 一些不成熟的运行时“功能”(x64上的3GB堆限制... WTF!)

但他说,一般而言,事情开始很快,解决方案/解决方法很多

一旦您克服了这些最初的障碍,我的经验就是mono ROCKS,并且每次迭代都会变得越来越好

我有运行单声道的服务器,每天处理300GB的数据,大量的p / invokes,一般来说,即使有“出血边缘”单声道,也要进行很多工作并保持5-6个月的运行时间。

希望这可以帮助。


1
你能告诉我(如果可以的话)你在说什么网站?
Christophe Debove 2012年

21

现在,有关已接受答案的建议有些过时了。

  • Windows窗体实现现在非常好。(有关Paint.net的端口,请参见Paint-Mono,Paint.net是一个非常复杂的Windows窗体应用程序。所需的只是一些P-Invoke和不受支持的系统调用的仿真层)。
  • Path.Combine以及Path.Seperator来连接路径和文件名。
  • Windows注册表是可以的,只要您仅将其用于存储和检索应用程序中的数据即可(即,由于它基本上是Mono应用程序的注册表,因此您无法从中获取有关Windows的任何信息)。

+1以便跟进...看来此页面可能已经过时了。
哈波

1
是的,Mono的一生都是以他们工作的速度来度过的。
克里斯·埃里克森

12

如果您想使用WPF,那么运气不好,Mono目前没有实现它的计划。

http://www.mono-project.com/WPF


3
真是太糟糕了。WPF是一个不错的UI工具包。
JP理查森,2009年

@JP理查森(Richardson)我明白您的意思-编程时很好-但如果它是从概念上构建的,并且打算成为一个非便携式工具箱,那么我就不会称其为“体面的”。
Wyatt8740

@ Wyatt8740我的评论写于10年前。
JP理查森

@JP理查森,哈哈,我不好。但是,即使十年前,它仍然不是便携式的。
Wyatt8740 '19

9

好吧,单声道很棒,但是据我所知,它是不稳定的。它可以工作,但是当您为单声道过程进行认真的工作时会出错。

TL; DR-如果您:

  • 在多线程环境中使用AppDomains(程序集加载\卸载)
  • 无法维持“让它失败”的模式
  • 在流程运行期间偶尔遇到重载事件

所以,事实。

我们在RHEL5,Ubuntu上使用mono-2.6.7(.net v 3.5),就我而言,它是Novell构建的最稳定的版本。它与卸载AppDomains有关(segfaults)有问题,但是,它失败的机会非常少,到目前为止(我们)可以接受。

好的。但是,如果要使用.net 4.0的功能,则必须切换到2.10.x或3.x版本,这才是问题开始的地方。

与2.6.7相比,不能接受使用新版本。我编写了一个简单的压力测试应用程序来测试单声道安装。

它在这里,并带有使用说明:https : //github.com/head-thrash/stress_test_mono

它使用线程池工作线程。Worker将dll加载到AppDomain并尝试执行一些数学工作。有些工作是多线程的,有些工作是单线程的。尽管从磁盘读取了一些文件,但是几乎所有工作都是受CPU限制的。

结果不是很好。实际上,对于版本3.0.12:

  • sgen GC segfaults几乎立即处理
  • Boehm的单声道寿命更长(从2到5个小时),但最终会出现段错误

如上所述,sgen gc不能正常工作(从源代码构建的单声道):

* Assertion: should not be reached at sgen-scan-object.h:111

Stacktrace:


Native stacktrace:

    mono() [0x4ab0ad]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0xfcb0) [0x2b61ea830cb0]
    /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x35) [0x2b61eaa74425]
    /lib/x86_64-linux-gnu/libc.so.6(abort+0x17b) [0x2b61eaa77b8b]
    mono() [0x62b49d]
    mono() [0x62b5d6]
    mono() [0x5d4f84]
    mono() [0x5cb0af]
    mono() [0x5cb2cc]
    mono() [0x5cccfd]
    mono() [0x5cd944]
    mono() [0x5d12b6]
    mono(mono_gc_collect+0x28) [0x5d16f8]
    mono(mono_domain_finalize+0x7c) [0x59fb1c]
    mono() [0x596ef0]
    mono() [0x616f13]
    mono() [0x626ee0]
    /lib/x86_64-linux-gnu/libpthread.so.0(+0x7e9a) [0x2b61ea828e9a]
    /lib/x86_64-linux-gnu/libc.so.6(clone+0x6d) [0x2b61eab31ccd]

至于boehm segfauls-例如(Ubuntu 13.04,从源代码构建的单声道):

mono: mini-amd64.c:492: amd64_patch: Assertion `0' failed.
Stacktrace:
at <unknown> <0xffffffff>
at System.Collections.Generic.Dictionary`2.Init (int,System.Collections.Generic.IEqualityComparer`1<TKey>) [0x00012] in /home/bkmz/my/mono/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:264
at System.Collections.Generic.Dictionary`2..ctor () [0x00006] in /home/bkmz/my/mono/mcs/class/corlib/System.Collections.Generic/Dictionary.cs:222
at System.Security.Cryptography.CryptoConfig/CryptoHandler..ctor (System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00014] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/Crypto
Config.cs:582
at System.Security.Cryptography.CryptoConfig.LoadConfig (string,System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00013] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoCo
nfig.cs:473
at System.Security.Cryptography.CryptoConfig.Initialize () [0x00697] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:457
at System.Security.Cryptography.CryptoConfig.CreateFromName (string,object[]) [0x00027] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:495
at System.Security.Cryptography.CryptoConfig.CreateFromName (string) [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:484
at System.Security.Cryptography.RandomNumberGenerator.Create (string) [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:59
at System.Security.Cryptography.RandomNumberGenerator.Create () [0x00000] in /home/bkmz/my/mono/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:53
at System.Guid.NewGuid () [0x0001e] in /home/bkmz/my/mono/mcs/class/corlib/System/Guid.cs:492

或(RHEL5,单声道来自rpm,此处为ftp://ftp.pbone.net/mirror/ftp5.gwdg.de/pub/opensuse/repositories/home%3A/vmas%3A/mono-centos5

Assertion at mini.c:3783, condition `code' not met
Stacktrace:
at <unknown> <0xffffffff>
at System.IO.StreamReader.ReadBuffer () [0x00012] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.IO/StreamReader.cs:394
at System.IO.StreamReader.Peek () [0x00006] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.IO/StreamReader.cs:429
at Mono.Xml.SmallXmlParser.Peek () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/Mono.Xml/SmallXmlParser.cs:271
at Mono.Xml.SmallXmlParser.Parse (System.IO.TextReader,Mono.Xml.SmallXmlParser/IContentHandler) [0x00020] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/Mono.Xml/SmallXmlParser.cs:346
at System.Security.Cryptography.CryptoConfig.LoadConfig (string,System.Collections.Generic.IDictionary`2<string, System.Type>,System.Collections.Generic.IDictionary`2<string, string>) [0x00021] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptog
raphy/CryptoConfig.cs:475
at System.Security.Cryptography.CryptoConfig.Initialize () [0x00697] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:457
at System.Security.Cryptography.CryptoConfig.CreateFromName (string,object[]) [0x00027] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:495
at System.Security.Cryptography.CryptoConfig.CreateFromName (string) [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/CryptoConfig.cs:484
at System.Security.Cryptography.RandomNumberGenerator.Create (string) [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:59
at System.Security.Cryptography.RandomNumberGenerator.Create () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Security.Cryptography/RandomNumberGenerator.cs:53
at System.Guid.NewGuid () [0x0001e] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System/Guid.cs:483
at System.Runtime.Remoting.RemotingServices.NewUri () [0x00020] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:356
at System.Runtime.Remoting.RemotingServices.Marshal (System.MarshalByRefObject,string,System.Type) [0x000ba] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System.Runtime.Remoting/RemotingServices.cs:329
at System.AppDomain.GetMarshalledDomainObjRef () [0x00000] in /usr/src/redhat/BUILD/mono-3.0.3/mcs/class/corlib/System/AppDomain.cs:1363

两种故障都以某种方式与AppDomains逻辑相关联,因此,您应远离Mono。

顺便说一句,经过测试的程序在MS .NET 4.5 env的Windows计算机上可以24小时正常工作。

因此,总而言之,我想说-谨慎使用mono。乍一看它是可行的,但是很容易在任何时候失败。在开放源代码项目中,您将面临一堆核心转储和重大信仰损失。


您是否尝试过在Xamarin bugzilla中提交错误?
MiKom 2014年



5

正如其他人所建议的那样,MoMA是一个很好的工具。如今,最大的不兼容性来源是将DllImport(或P / Invoke)导入Win32库的应用程序。某些程序集尚未实现,但大多数程序集仅适用于Windows,在Linux上确实没有意义。我认为可以肯定地说大多数ASP.NET应用程序可以在经过有限修改的Mono上运行。

(公开:我为Mono本身以及在其之上运行的书面应用程序做出了贡献。)


4
那就是Mono迁移分析仪,适合任何想知道与现代艺术博物馆有什么关系的人。
Ferruccio

4

在许多情况下,您可以采用现有代码并仅在Mono上运行它,尤其是在移植ASP.NET应用程序时。

在某些情况下,您可能需要全新的代码部分才能使其正常工作。例如,如果使用System.Windows.Forms,则该应用程序将无法正常运行。同样,如果您使用任何Windows特定的代码(例如,注册表访问代码)。但是我认为最糟糕的是UI代码。在Macintosh系统上,这尤其糟糕。


4

我们一直在将它用于需要在Linux上运行但仍重复使用我们在托管C ++中构建的.NET库的项目中。我对它的效果感到非常惊讶。我们的主要可执行文件是用C#编写的,我们可以毫无问题地引用托管C ++二进制文件。Windows和Linux之间C#代码的唯一区别是RS232串行端口代码。

我能想到的唯一大问题发生在一个月前。Linux版本有内存泄漏,而Windows版本中没有。经过一些手动调试(Linux上Mono的基本探查器没有多大帮助),我们能够将问题缩小到特定的代码块。我们最终修补了一种解决方法,但是我仍然需要花一些时间来回溯,找出导致泄漏的根本原因。


那么,如何为处理这两个问题的串行端口编写代码?CLR / Mono的重点是平台无关,对吗?这是在配置文件中完成的吗?
蒂姆

2

您知道Mono 2.0预览版对Windows Forms 2.0的支持有多好吗?

从我玩过的一点点来看,它似乎比较完整,几乎可以使用。它只是在某些地方看起来不太合适,总体上还是有点命中或错过的。坦白地说,它与我们的某些表单一样出色地工作,这让我感到惊讶。


2

是的,肯定是(如果您要小心的话)我们在Ra-Ajax中支持Mono(Ajax库位于http://ra-ajax.org。而且我们几乎没有任何问题。您需要谨慎处理诸如WSE等.Net中的一些“最疯狂的东西”,而且可能您现有的项目中有相当一部分不是100%Mono兼容的,但是如果您在开发过程中对其进行测试,则新项目将大部分与Mono兼容没有问题。通过使用Mono支持Linux等获得的收益真的很酷;)

我认为支持Mono的很大一部分秘诀就是从一开始就使用正确的工具,例如ActiveRecord,log4net,ra-ajax等。


2

对于我们正在构建的应用程序类型,不幸的是,Mono似乎尚未准备好投入生产。我们对它的整体印象深刻,并对其在Windows和EC2机器上的性能印象深刻,但是,我们的程序在Windows和Linux上都始终由于垃圾回收错误而崩溃。

错误消息是:“ GC中的严重错误:堆部分太多”,这是指向其他遇到问题的人的链接,其方式略有不同:

http://bugzilla.novell.com/show_bug.cgi?id=435906

我们在Mono中运行的第一段代码是我们开发的一个简单的编程挑战。代码将大约10mb的数据加载到某些数据结构(例如HashSets)中,然后对这些数据运行10个查询。我们对查询进行了100次运行,以便对它们进行计时并获得平均值。

该代码在Windows上的第55条查询附近崩溃了。在linux上它可以工作,但是一旦我们移至更大的数据集,它也会崩溃。

这段代码非常简单,例如,将一些数据放入HashSet中,然后查询这些HashSet等,所有本机c#,没有不安全的地方,没有API调用。在Microsoft CLR上,它永远不会崩溃,并且可以在海量数据集上运行1000倍。

我们中的一个人通过电子邮件给Miguel发送了电子邮件,其中包含了导致该问题的代码,但尚未得到答复。:(

似乎还有许多其他人在没有解决方案的情况下遇到了此问题-已建议一种解决方案,以不同的GC设置重新编译Mono,但这似乎增加了崩溃前的阈值。


9
Bugzilla是报告错误的地方:Miguel非常忙,没有人能跟上向每个人发送个人错误报告的步伐。如果您无法发布示例代码,则仍应在bugzilla中报告该问题,并注意那里已将示例发送给Miguel或我(lupus@ximian.com)。
狼疮

2

只需检查www.plasticscm.com。一切(客户端,服务器,GUI,合并工具)均以Mono编写。


1

它实际上取决于您从.NET Framework使用的名称空间和类。我有兴趣将自己的Windows服务之一转换为在我的电子邮件服务器Suse上运行,但是遇到了一些API尚未完全实现的硬障碍。Mono网站上某处的图表列出了所有课程及其完成程度。如果您的申请被涵盖,那就继续吧。

与其他任何应用程序一样,当然,在做出全部承诺之前,请进行原型设计和测试。

我们遇到的另一个问题是许可软件:如果您引用其他人的DLL,则无法绕过该程序集中存在的不兼容性进行编码。



1

不,单声道尚未准备好进行认真的工作。我在Windows上使用F#编写了一些程序,并在Mono上运行了它们。这些程序大量使用磁盘,内存和cpu。我看到了Mono库(托管代码)崩溃,本机代码崩溃以及虚拟机崩溃。当单声道工作时,程序比Windows中的.Net慢至少两倍,并且使用更多的内存。远离单声道进行认真的工作。


4
这是事实的轶事证据,并以FUD的形式出现在我
面前

实际上,在nginx / fast-cgi下运行ASP.NET比在IIS上运行更快。这完全取决于框架的哪一部分已移植/是否经过良好测试:mono-project.com/Compatibility。必须同意@firegrass。
Rui Marques

1
这就是一个人的个人经历。除了以“我认为”作为前缀外,这是对本次讨论的有效贡献。
阿米尔·阿比里
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.