小编Bry*_*ner的帖子

在.NET 4.0中,P/Invoke环境是否发生了变化?

我已经开始将.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)

delphi pinvoke .net-4.0

13
推荐指数
1
解决办法
1643
查看次数

.NET有多个集合的内置IEnumerable吗?

我需要一种简单的方法来迭代多个集合而不实际合并它们,我找不到任何内置于.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)

.net c# ienumerable

8
推荐指数
2
解决办法
836
查看次数

Visual Studio探查器,如何跟踪[clr.dll]用法

在Visual Studio中使用分析器来跟踪昂贵的功能时,我偶尔会看到大多数工作最终都在[clr.dll]中.这基本上相当于一个黑盒子,我想知道是否有办法找出为什么它花了那么多时间在那里.

我假设clr.dll处理诸如JIT编译,加载程序集和管理appdomains,垃圾收集,反射等等之类的东西.但它实际上很难确定哪些代码导致它花费这么多时间.

显然除了运行时本身之外还有一些其他代码会导致它在clr.dll中花费那么多时间,那么如何追踪哪些代码有问题呢?

.net profiler visual-studio

8
推荐指数
1
解决办法
4194
查看次数

有效改变100GB表的方法

我们有许多数据库,在其中一个表中存储10到100千兆字节的数据.它包含图像数据.问题是很多这些数据库都是不正确地创建的.基本上,主键实际上不是主键.在可空列上使用唯一索引创建.其中一些有一个int作为主键而不是bigint.

所以我们一直在慢慢地修复这些数据库.它们通过SQL Server 2008在SQL Server 2000上运行,尽管大多数具有主键问题的都在SQL Server 2000上.问题是,我们不希望在转换表时将数据库锁定一整天.我们经历了几个策略:

  1. 告诉SQL Server直接更改列类型.这会锁定桌子直到它完成,并且在很多情况下将它放置一夜之后,它仍然没有完成.

  2. 一次性将所有图像插入新表中.这更容易被中断,但整个表基本上都被写入了进程中的日志文件.

  3. 在目标表中不存在行的时间插入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%的工作.

bulkinsert sql-server-2000

7
推荐指数
1
解决办法
764
查看次数

SQL无效转换返回null而不是抛出错误

我有一个带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?

t-sql invalid-characters

7
推荐指数
2
解决办法
9133
查看次数

为什么统计数据在SQL Server中如此快速地过时?

我们有一个有点复杂的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)

sql-server statistics sql-server-2000

6
推荐指数
1
解决办法
2215
查看次数

可以将PDF转换为可以从.NET打印的矢量图像格式吗?

我们有一个.NET应用程序可以打印到真正的打印机和PDF,目前使用的是PDFsharp,但如果有更好的选择,可以更改该部分.大多数输出​​是生成的文本或图像,但可以有一个或多个页面附加到末尾.该页面由最终用户以PDF格式提供.

打印到纸张时,我们的用户使用预先打印的纸张,但在导出PDF的情况下,我们会将这些页面连接到最后,因为它们已经是PDF格式.

我们希望能够将这些PDF直接嵌入到打印流中,因此它们不需要预先打印的纸张.但是,将PDF转换为GDI页面(System.Drawing.Graphics)并没有什么好的选择.

是否有一种矢量格式,PDF可以通过某些外部程序转换为可以转换为GDI +页面而不会因首先转换为位图而降级?

c# pdf gdi vector-graphics

6
推荐指数
1
解决办法
3770
查看次数

SQL 2000 UNION ALL废墟查询优化

我有一个存储过程,需要一秒钟才能正常运行.用户需要来自该查询中另一个表的数据,因此我将该数据与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)

sql-server query-optimization union-all

5
推荐指数
1
解决办法
1171
查看次数

如何检测MemoryMappedFile是否正在使用中

在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打开,以确定当处理当前句柄时文件是否将被关闭?

c# memory-mapped-files

5
推荐指数
1
解决办法
3055
查看次数

没有第二种形式的多线程消息泵送

我有一个使用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最终在原始线程上),等等.我没有尝试过.

c# com multithreading synchronizationcontext

4
推荐指数
1
解决办法
1292
查看次数

在数据库之外存储主键生成器的安全方法?

我们有一个应用程序将其数据存储在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这样的解决方案做了一些考虑,但这本身就存在问题.

sql filesystems primary-key

3
推荐指数
1
解决办法
321
查看次数

不区分大小写将字符串与非字符串进行比较

我创建了一个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)

c# string equals case-insensitive

2
推荐指数
1
解决办法
1845
查看次数

C#为DSA加密算法生成公钥和私钥

如何以字节数组格式生成DSA算法的公钥和私钥?

c# encryption public-key-encryption dsa

2
推荐指数
1
解决办法
2605
查看次数