小编Bob*_*man的帖子

如何使“await using”语法正确?

我有以下同步代码,运行良好:

    private void GenerateExportOutput()
    {
        using StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");

        if (this.WikiPagesToExport.IsEmpty)
        {
            return;
        }

        var wanted = new SortedDictionary<string, WikiPage>(this.WikiPagesToExport, StringComparer.Ordinal);
        foreach (var title in wanted.Keys)
        {
            writer.WriteLine(title);
        }
    }
Run Code Online (Sandbox Code Playgroud)

我想将其更改为异步。所以:

    private async Task GenerateExportOutputAsync()
    {
        using StreamWriter writer = new(Coordinator.OutputDirectory + @"\export.txt");

        if (this.WikiPagesToExport.IsEmpty)
        {
            return;
        }

        var wanted = new SortedDictionary<string, WikiPage>(this.WikiPagesToExport, StringComparer.Ordinal);
        foreach (var title in wanted.Keys)
        {
            await writer.WriteLineAsync(title).ConfigureAwait(false);
        }

        await writer.FlushAsync().ConfigureAwait(false);
    }
Run Code Online (Sandbox Code Playgroud)

哪个编译。但我使用的分析器之一(Meziantou.Analyzer)现在建议我“更喜欢使用‘await using’”。我从来没有使用过await using(尽管我过去尝试过几次并且总是遇到现在遇到的相同问题)。但我想使用它,所以:

        await using StreamWriter writer = …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous async-await iasyncdisposable

10
推荐指数
1
解决办法
2801
查看次数

基于异步/等待的Windows服务中的同步I/O.

假设我有一个Windows服务,它正在做一些工作,然后在很长一段时间内一直睡眠,一直到来(直到服务关闭).所以在服务的OnStart中,我可以启动一个线程,其入口点如下:

private void WorkerThreadFunc()
{
    while (!shuttingDown)
    {
        DoSomething();
        Thread.Sleep(10);
    }
}
Run Code Online (Sandbox Code Playgroud)

在服务的OnStop中,我以某种方式设置了shuttingDown标志然后加入线程.实际上可能有几个这样的线程,以及其他线程,都在OnStart中启动并在OnStop中关闭/加入.

如果我想在基于async/await的Windows服务中执行此类操作,似乎我可以让OnStart创建可取消的任务但不等待(或等待)它们,并让OnStop取消这些任务然后Task.WhenAll ().等等().如果我理解正确,上面显示的"WorkerThreadFunc"的等价物可能是这样的:

private async Task WorkAsync(CancellationToken cancel)
{
    while (true)
    {
        cancel.ThrowIfCancellationRequested();
        DoSomething();
        await Task.Delay(10, cancel).ConfigureAwait(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题1:呃......对吗?我是异步/等待的新手,仍然试图了解它.

假设这是正确的,现在让我们说DoSomething()调用是(或包括)某些硬件的同步写入I/O. 如果我理解正确:

问题2:那不好?我不应该在基于async/await的程序中的Task中进行同步I/O操作?因为它在I/O发生时从线程池中占用一个线程,而线程池中的线程是一个非常有限的资源?请注意,我可能会有数十名此类工作人员同时使用不同的硬件.

我不确定我是否理解正确 - 我认为这与Stephen Cleary的文章" Task.Run Etiquette例子:不要使用Task.Run错误的东西 "有关,但这是特别关于它的存在在Task.Run中做阻塞工作很糟糕.我不确定如果我只是直接这样做也不好,就像上面的"私人异步任务工作()"例子一样?

假设这也很糟糕,那么如果我理解正确,我应该使用DoSomething的非阻塞版本(如果它尚不存在则创建非阻塞版本),然后:

private async Task WorkAsync(CancellationToken cancel)
{
    while (true)
    {
        cancel.ThrowIfCancellationRequested();
        await DoSomethingAsync(cancel).ConfigureAwait(false);
        await Task.Delay(10, cancel).ConfigureAwait(false);
    }
}
Run Code Online (Sandbox Code Playgroud)

问题3:但是......如果DoSomething来自第三方库,我必须使用并且不能更改,并且该库不会公开DoSomething的非阻塞版本,该怎么办?它只是一个黑色的盒子,在某些时候阻止写入一块硬件.

也许我包装它并使用TaskCompletionSource?就像是:

private async Task WorkAsync(CancellationToken cancel)
{
    while (true)
    {
        cancel.ThrowIfCancellationRequested();
        await WrappedDoSomething().ConfigureAwait(false);
        await Task.Delay(10, cancel).ConfigureAwait(false);
    }
}

private …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous async-await

9
推荐指数
1
解决办法
3093
查看次数

NamedPipeServerStream.BeginWaitForConnection 因 System.IO.Exception 失败:管道正在关闭

我用 C# 编写了一个简单的异步 NamedPipeStreamServer 进程,其核心是:

public void Listen()
{
    bool shuttingDown = false;
    while (!shuttingDown)
    {
        NamedPipeServerStream serverStream =
            new NamedPipeServerStream(
                "bobasdfpipe",
                PipeDirection.InOut,
                254,
                PipeTransmissionMode.Message,
                PipeOptions.Asynchronous);

        IAsyncResult connectionResult = 
                serverStream.BeginWaitForConnection(
                    this.HandleConnection,
                    serverStream);

        int waitResult =
            WaitHandle.WaitAny(
                new[]
                    {
                        this.ShutdownEvent,
                        connectionResult.AsyncWaitHandle
                    });
        switch (waitResult)
        {
            case 0:
                // this.ShutdownEvent
                shuttingDown = true;
                break;

            case 1:
                // connectionResult.AsyncWaitHandle
                serverStream.EndWaitForConnection(connectionResult);
                break;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我还为它编写了一个简单的客户端。客户端(不是异步的)只是打开管道然后退出:

static void Main(string[] args)
{
    using (
        NamedPipeClientStream clientStream =
            new NamedPipeClientStream(
                ".",
                "bobasdfpipe",
                PipeDirection.InOut))
    {
        clientStream.Connect();
    } …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous named-pipes namedpipeserverstream

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

温莎城堡:"LoggingFacility.UseNLog()已过时"

很久以前,我做了一个小项目,我希望了解温莎城堡.我把它放在一边(在真正学到这么多之前)已经有一段时间了.我现在再次打开它,并更新了NuGet包,并开始收到警告CS0618:

'LoggingFacility.UseNLog()'已经过时了:'应该通过LogUsing()提供记录器工厂实现类型,将来会删除它.

我已经基于此搜索了,但我仍然不清楚我应该做什么来取代现在过时的调用,即:

container.AddFacility<LoggingFacility>(f => f.UseNLog());
Run Code Online (Sandbox Code Playgroud)

任何帮助,将不胜感激.谢谢!

.net logging castle-windsor nlog

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

如何用UBound &lt;LBound制作VB6变体数组?

我试图摆脱对VB6应用程序中SCRRUN.DLL的依赖。它当前用于其中的一件事是其Dictionary类。Dictionary类具有一个Keys函数,该函数应该返回字典中的一个键数组。我做了一些实验,看看字典中没有键会发生什么:

Dim D As Dictionary
Set D = New Dictionary
Dim K() As Variant
K = D.Keys
MsgBox LBound(K) & ", " & UBound(K)
Run Code Online (Sandbox Code Playgroud)

我原以为“下标超出范围”或类似的内容,但是我却得知LBound为0,UBound为-1。

那么,如何创建具有LBound 0和UBound -1的Variant数组?

我试过只使用未初始化的变体数组:

Dim K() as Variant
MsgBox LBound(K) & ", " & UBound(K)
Run Code Online (Sandbox Code Playgroud)

但是,当然,正如我所期望的那样,这会使“下标超出范围”。删除未初始化的数组也是如此:

Dim K() as Variant
Erase K
MsgBox LBound(K) & ", " & UBound(K)
Run Code Online (Sandbox Code Playgroud)

与擦除初始化数组一样:

Dim K() As Variant
ReDim K(0 To 0)
Erase K
MsgBox LBound(K) & ", " & UBound(K)
Run Code Online (Sandbox Code Playgroud)

我还尝试过仅将其重新设置为0和-1,这看起来很奇怪:

Dim K() As Variant
ReDim K(0 To …
Run Code Online (Sandbox Code Playgroud)

arrays vb6 variant

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