我已经开始将.NET 2.0 WinForms应用程序升级到.NET 4.0.嗯,好的,升级过程只是切换平台目标,但让它真正起作用.我认为这就是它的全部内容.
但似乎.NET 4.0中关于互操作的东西发生了巨大的变化.使用DllImport(),该应用程序嵌入了几个Delphi dll.当应用程序面向.NET 2.0时,一切正常.但是当我将它改为目标.NET 4.0时,东西开始变得混乱,就像破坏内存的东西一样.
例如,它在奇怪的地方用"0"替换单个数字.在IStream中传递的数据用(Hex)00 00 00 00 00 00 00 80替换8个字符,但只有大约70%的时间.两次连续调用以检索相同的值会返回不同的结果(从内存中的缓存中检索值,第一次成功,第二次失败).发送到日志的字符串显示为截断.
我尝试过很多尝试使调用约定更加明确的东西,没有任何效果.所有字符串在.NET端处理为[MarshalAs(UnmanagedType.LPWStr)],在Delphi端处理为PWChar.
在.NET 4.0中改变了什么会破坏P/Invoke?
- - - - - - - - - - - - - - 编辑 - - - - - - - - - - - ----------------
这是最简单的例子.它生成一个PDF,有时可以正常工作,但更频繁地最终损坏(并在.NET 2.0中正常工作):
[DllImport(DLLName)]
public static extern void SetDBParameters(
[MarshalAs(UnmanagedType.LPWStr)] string Server,
[MarshalAs(UnmanagedType.LPWStr)] string Database,
[MarshalAs(UnmanagedType.LPWStr)] string User,
[MarshalAs(UnmanagedType.LPWStr)] string Password,
short IntegratedSecurity);
procedure SetDBParameters(Server, Database, User, Password: PWChar;
IntegratedSecurity: WordBool); stdcall;
[DllImport(DLLName)]
public …Run Code Online (Sandbox Code Playgroud) 我需要一种简单的方法来迭代多个集合而不实际合并它们,我找不到任何内置于.NET中的内容.感觉这应该是一种常见的情况.我不想重新发明轮子.有什么内置的东西是这样的:
public class MultiCollectionEnumerable<T> : IEnumerable<T>
{
private MultiCollectionEnumerator<T> enumerator;
public MultiCollectionEnumerable(params IEnumerable<T>[] collections)
{
enumerator = new MultiCollectionEnumerator<T>(collections);
}
public IEnumerator<T> GetEnumerator()
{
enumerator.Reset();
return enumerator;
}
IEnumerator IEnumerable.GetEnumerator()
{
enumerator.Reset();
return enumerator;
}
private class MultiCollectionEnumerator<T> : IEnumerator<T>
{
private IEnumerable<T>[] collections;
private int currentIndex;
private IEnumerator<T> currentEnumerator;
public MultiCollectionEnumerator(IEnumerable<T>[] collections)
{
this.collections = collections;
this.currentIndex = -1;
}
public T Current
{
get
{
if (currentEnumerator != null)
return currentEnumerator.Current;
else
return default(T);
}
}
public void …Run Code Online (Sandbox Code Playgroud) 在Visual Studio中使用分析器来跟踪昂贵的功能时,我偶尔会看到大多数工作最终都在[clr.dll]中.这基本上相当于一个黑盒子,我想知道是否有办法找出为什么它花了那么多时间在那里.
我假设clr.dll处理诸如JIT编译,加载程序集和管理appdomains,垃圾收集,反射等等之类的东西.但它实际上很难确定哪些代码导致它花费这么多时间.
显然除了运行时本身之外还有一些其他代码会导致它在clr.dll中花费那么多时间,那么如何追踪哪些代码有问题呢?
我们有许多数据库,在其中一个表中存储10到100千兆字节的数据.它包含图像数据.问题是很多这些数据库都是不正确地创建的.基本上,主键实际上不是主键.在可空列上使用唯一索引创建.其中一些有一个int作为主键而不是bigint.
所以我们一直在慢慢地修复这些数据库.它们通过SQL Server 2008在SQL Server 2000上运行,尽管大多数具有主键问题的都在SQL Server 2000上.问题是,我们不希望在转换表时将数据库锁定一整天.我们经历了几个策略:
告诉SQL Server直接更改列类型.这会锁定桌子直到它完成,并且在很多情况下将它放置一夜之后,它仍然没有完成.
一次性将所有图像插入新表中.这更容易被中断,但整个表基本上都被写入了进程中的日志文件.
在目标表中不存在行的时间插入100行.好处是,他们可以继续使用数据库进行此操作(性能大幅提升),并且可以在任何时候任意停止和重新启动,并且它可以防止100GB +日志文件.这就是我们目前正在做的事情,但是随着目标表变得越来越大,找到不存在的前100行变得非常慢.UPDATE STATISTICS和DBCC INDEXDEFRAG有很大的帮助,但在最近的尝试中,我们达到了这一点,一次只有100张图像坐在那里没有响应.
INSERT INTO %s
SELECT TOP 100 Source.*
FROM %s AS Source WITH (NOLOCK)
LEFT OUTER JOIN %s AS Target WITH (NOLOCK) ON Source.DocumentID = Target.DocumentID
WHERE Target.DocumentID IS NULL
ORDER BY Source.DocumentID
Run Code Online (Sandbox Code Playgroud)所以问题是,是否有可以以高效和可恢复的方式复制批量数据的选项?它不必100%准确,我们总是可以返回并修复最后的任何差异,只要它完成99%的工作.
我有一个带varchar列的表,我想找到与某个数字匹配的值.因此,我们可以说该列包含以下条目(现实生活中除了数百万行):
123456789012
2345678
3456
23 45
713?2
00123456789012
Run Code Online (Sandbox Code Playgroud)
所以我决定我想要所有数字上的行123456789012写一个看起来像这样的语句:
SELECT * FROM MyTable WHERE CAST(MyColumn as bigint) = 123456789012
Run Code Online (Sandbox Code Playgroud)
它应该返回第一行和最后一行,但整个查询会爆炸,因为它无法将"23 45"和"713?2"转换为bigint.
是否有另一种方法可以进行转换,为无法转换的值返回NULL?
我们有一个有点复杂的SQL更新查询,每月运行几次.它大部分时间似乎运行得非常快,但在某些数据库上,它需要很长时间.在所涉及的表上运行"UPDATE STATISTICS"后,更新会立即再次快速运行.我们最终设置了一个夜间任务,它在数据库中的所有表上调用UPDATE STATISTICS.但这似乎没有解决问题.我们最终还是必须每次手动运行"UPDATE STATISTICS".为什么统计数据会如此迅速地过时?
这是查询的大致内容:
UPDATE DataTableA
SET DataTableA.IndexedColumn1 = 123456789, DataTableA.Flag1 = 1
FROM DataTableA WITH (INDEX(IX_DataTableA))
INNER JOIN GroupingTableA ON GroupingTableA.ForeignKey1 = GroupingTableA.PrimaryKey
INNER JOIN LookupTableA ON DataTableA.ForeignKey3 = LookupTableA.PrimaryKey
LEFT OUTER JOIN GroupingTableB ON DataTableA.IndexedColumn2 = GroupingTableB.IndexedColumn2
WHERE GroupingTableB.IndexedColumn1 = 123456789
AND DataTableA.IndexedColumn1 IS NULL
AND DataTableA.IndexedColumn2 IN ( ... 300 entries here ... )
AND DataTableA.Deleted = 0
AND GroupingTableA.Date <= GroupingTableB.EndDate
AND GroupingTableA.Date >= DATEADD(month, -1, GroupingTableB.StartDate)
AND LookupTableA.Column2 = 1
AND DataTableA.Status1 IN (1, …Run Code Online (Sandbox Code Playgroud) 我们有一个.NET应用程序可以打印到真正的打印机和PDF,目前使用的是PDFsharp,但如果有更好的选择,可以更改该部分.大多数输出是生成的文本或图像,但可以有一个或多个页面附加到末尾.该页面由最终用户以PDF格式提供.
打印到纸张时,我们的用户使用预先打印的纸张,但在导出PDF的情况下,我们会将这些页面连接到最后,因为它们已经是PDF格式.
我们希望能够将这些PDF直接嵌入到打印流中,因此它们不需要预先打印的纸张.但是,将PDF转换为GDI页面(System.Drawing.Graphics)并没有什么好的选择.
是否有一种矢量格式,PDF可以通过某些外部程序转换为可以转换为GDI +页面而不会因首先转换为位图而降级?
我有一个存储过程,需要一秒钟才能正常运行.用户需要来自该查询中另一个表的数据,因此我将该数据与UNION ALL以及新表中缺少的一堆虚拟列合并.
它在测试中运行良好,但是当我们将它部署到SQL 2000 Server时,它开始超时.旧查询在一秒钟内运行,并且2个新查询都在一秒钟内运行,但是当它们使用UNION ALL组合时,查询超时.
以下是查询外观的一般概念.真正的查询有大约20个输入参数,并返回大约30或40列,但这应该给出基本的想法:
CREATE PROCEDURE dbo.SearchHistory
(
@Criteria1 bigint,
@Criteria2 int,
@Criteria3 varchar(10)
)
AS
BEGIN
-- Part 1
SELECT
A,
NULL AS B,
0 AS C,
D
FROM TableA
WHERE @Criteria1 IS NULL
AND @Criteria3 IS NULL
AND (A = @Criteria2 OR @Criteria2 IS NULL)
UNION ALL
-- Part 2
SELECT
A,
NULL AS B,
0 AS C,
E
FROM TableA
WHERE @Criteria1 IS NULL
AND @Criteria3 IS NULL
AND (A = @Criteria2 OR @Criteria2 …Run Code Online (Sandbox Code Playgroud) 在C#4.0中,MemoryMappedFile有几个工厂方法:CreateFromFile,CreateNew,CreateOrOpen,或OpenExisting.我需要打开MemoryMappedFile它是否存在,如果不存在,则从文件中创建它.我打开内存映射的代码如下所示:
try
{
map = MemoryMappedFile.OpenExisting(
MapName,
MemoryMappedFileRights.ReadWrite
| MemoryMappedFileRights.Delete);
}
catch (FileNotFoundException)
{
try
{
stream = new FileStream(
FileName,
FileMode.OpenOrCreate,
FileAccess.ReadWrite,
FileShare.Read | FileShare.Delete);
map = MemoryMappedFile.CreateFromFile(
stream, MapName, length + 16,
MemoryMappedFileAccess.ReadWrite,
null,
HandleInheritability.None,
false);
}
catch
{
if (stream != null)
stream.Dispose();
stream = null;
}
}
Run Code Online (Sandbox Code Playgroud)
它几乎按照我想要的方式工作,但最终OpenExisting会经常抛出异常.MemoryMappedFile在尝试OpenExisting拨打电话之前,有没有办法检查实际存在?或者我每次都必须处理异常?
此外,有没有办法找出当前句柄是否是最后一个MemoryMappedFile打开,以确定当处理当前句柄时文件是否将被关闭?
我有一个使用COM组件的C#应用程序.此COM组件需要消息泵(Application.Run())来执行其处理.这意味着它一直停留在主线程上.但是我最近发现可以在另一个获得自己的ApplicationContext的线程上启动另一个Application.Run.
所以我想在其自己的Application.Run()中将COM组件托管在自己的线程上,但我无法弄清楚如何在不创建UI表单的情况下在新线程上启动.
我需要与线程通信的WindowsFormsSynchronizationContext才会在Application.Run()之前创建.但是一旦调用了Application.Run(),我就无法弄清楚如何获得SynchronizationContext.如果我可以在该线程上引发单个事件,我可以使用它来引导整个事物(创建COM对象等),但似乎没有任何地方可以挂钩到没有表单的新事件循环.
我尝试了各种复杂的东西,比如安装一个消息过滤器(在新线程上没有引发消息),将执行上下文复制到另一个线程并尝试从那里检索SynchronizationContext(它拒绝复制一个ExecutionContext已经运行线程),在启动Application.Run()之前检索Thread.CurrentContext,然后调用DoCallbBack()(DoCallback最终在原始线程上),等等.我没有尝试过.
我们有一个应用程序将其数据存储在SQL Server中.每个表都有一个bigint主键.我们过去只是按需生成这些,即当你去插入一个新行时,你首先调用生成下一个ID,然后你进行插入.
我们添加了对在脱机模式下运行的支持:如果连接断开(或SQL Server已关闭),它会将数据保存到本地文件,直到您重新联机,然后同步您从那时起所做的所有事情.
这需要能够在客户端生成ID.它不是要求SQL提供下一个ID,而是要求下一百或者千或10,000个ID,然后在本地存储该范围,因此在10,000个用完之前不需要更多.它实际上会将它们放在较小的块中,所以当5000用完时,它仍然有5000的缓冲区,它可以要求5000多个.
问题是,一旦上线,我们就开始收到主要密钥违规的报告.我们将数据存储在Windows注册表中的HKEY_CURRENT_USER中(保证用户可以写入的注册表中唯一的位置).因此,经过一些研究,我们发现HKEY_CURRENT_USER是漫游配置文件的一部分,因此ID可能会被旧版本覆盖.特别是如果用户同时登录网络上的多台计算机.
因此,我们重新编写了生成ID的部分,以便从用户的"Local Settings"目录中读取/写入文件.当然不应该被旧版本覆盖.但即使是现在,我仍然偶尔会看到主键违规.在这种情况下,我们唯一可以做的就是删除文件中的任何键,将用户踢出应用程序,并且在获得新的ID范围之前不要让它们重新进入.
但如果"本地设置"不安全,会是什么?是否有任何地方可以在计算机上存储持久值,保证不会回滚到旧版本?任何人都可以解释为什么"本地设置"不符合此标准?
我已经对GUID这样的解决方案做了一些考虑,但这本身就存在问题.
我创建了一个C#结构,它可以透明地处理不区分大小写的字符串比较.例如:
List<IString> list = new List<IString>();
list.Add("help");
Assert.IsTrue(list.Contains("Help"));
Run Code Online (Sandbox Code Playgroud)
要么
Dictionary<IString, string> dict = new Dictionary<IString, string>();
dict["Help"] = "thanks!";
Assert.AreEqual("thanks!", dict["hELP"]);
Run Code Online (Sandbox Code Playgroud)
但是我无法弄清楚的一件事(也许是不可能的)是如何让类字符串在.Equals(object)中很好地发挥作用:
IString A1 = "A";
string A2 = "a";
Assert.AreEqual(A1, A2, "This passes");
Assert.AreEqual(A2, A1, "This fails");
Run Code Online (Sandbox Code Playgroud)
这是代码:
using System;
using System.Collections.Generic;
namespace Util
{
/// <summary>
/// Case insensitive wrapper for the string class
/// </summary>
public struct IString :
IComparer<IString>,
IComparable,
IComparable<IString>,
IComparable<string>,
IEquatable<string>,
IEquatable<IString>
{
private const StringComparison icase = StringComparison.OrdinalIgnoreCase;
public readonly string Value;
public …Run Code Online (Sandbox Code Playgroud) 如何以字节数组格式生成DSA算法的公钥和私钥?
c# ×6
.net ×2
sql-server ×2
.net-4.0 ×1
bulkinsert ×1
com ×1
delphi ×1
dsa ×1
encryption ×1
equals ×1
filesystems ×1
gdi ×1
ienumerable ×1
pdf ×1
pinvoke ×1
primary-key ×1
profiler ×1
sql ×1
statistics ×1
string ×1
t-sql ×1
union-all ×1