小编The*_*ias的帖子

为什么TaskScheduler.Current是默认的TaskScheduler?

任务并行库很棒,在过去的几个月里我经常使用它.但是,有一些事情让我感到困扰:事实TaskScheduler.Current是默认的任务调度程序,而不是TaskScheduler.Default.这在文档和样本中乍一看绝对不是很明显.

Current可以导致细微的错误,因为它的行为正在改变,这取决于你是否在另一个任务中.哪个不容易确定.

假设我正在编写异步方法库,使用基于事件的标准异步模式来表示原始同步上下文的完成,这与XxxAsync方法在.NET Framework中完全相同(例如DownloadFileAsync).我决定使用任务并行库来实现,因为使用以下代码实现此行为非常容易:

public class MyLibrary
{
    public event EventHandler SomeOperationCompleted;

    private void OnSomeOperationCompleted()
    {
        SomeOperationCompleted?.Invoke(this, EventArgs.Empty);
    }

    public void DoSomeOperationAsync()
    {
        Task.Factory.StartNew(() =>
        {
            Thread.Sleep(1000); // simulate a long operation
        }, CancellationToken.None, TaskCreationOptions.None, TaskScheduler.Default)
        .ContinueWith(t =>
        {
            OnSomeOperationCompleted(); // trigger the event
        }, TaskScheduler.FromCurrentSynchronizationContext());
    }
}
Run Code Online (Sandbox Code Playgroud)

到目前为止,一切运作良好.现在,让我们在WPF或WinForms应用程序中单击按钮调用此库:

private void Button_OnClick(object sender, EventArgs args)
{
    var myLibrary = new MyLibrary();
    myLibrary.SomeOperationCompleted += (s, e) => DoSomethingElse();
    myLibrary.DoSomeOperationAsync(); // call that triggers the …
Run Code Online (Sandbox Code Playgroud)

.net c# conceptual synchronizationcontext task-parallel-library

61
推荐指数
3
解决办法
2万
查看次数

具有多个构造函数的记录类型

如何在 C# 中为记录类型创建多个构造函数?

我创建了这样的记录类型:

public record Person(int Id, string FirstName, string LastName)
Run Code Online (Sandbox Code Playgroud)

现在我想引入另一个不带参数的构造函数重载,我该怎么做?在正常的课堂上我会做这样的事情:

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public Person()
    {
        
    }

    public Person(int id, string firstName, string lastName)
    {
        Id = id;
        FirstName = firstName;
        LastName = lastName;
    }
}
Run Code Online (Sandbox Code Playgroud)

.net c# c#-9.0

43
推荐指数
4
解决办法
3万
查看次数

如何在 C# 中从字典中删除 KEY

我有一本名为d如上所述的字典。

Dictionary<string, int> d = new Dictionary<string, int>();
    d["dog"] = 1;
    d["cat"] = 5;
Run Code Online (Sandbox Code Playgroud)

现在,如果我想删除密钥,"cat"我无法使用该Remove()方法,因为它只删除关联的相应值,而不删除密钥本身。那么有没有办法删除密钥呢?

c# dictionary key

20
推荐指数
2
解决办法
3万
查看次数

使用 Parallel.ForEachAsync

我正在尝试运行 a Parallel.ForEachAsync(),但出现以下两个错误:

错误 1:
参数 2:无法从 System.Threading.Tasks.ParallelOptions 转换为 System.Threading.CancellationToken
错误 2:
Delegate Func<WC, CancellationToken, ValueTask> 不采用 1 个参数

这是我的代码:

public async Task<List<DisplayDto>> GetData()
{
    var options = new ParallelOptions()
    {
        MaxDegreeOfParallelism = 20;
    };

    await Parallel.ForEachAsync(result, options, async OrderNumber => {
        //Do Stuff here. 
    });
}
Run Code Online (Sandbox Code Playgroud)

为了使其按照我的要求工作,必须改变什么?

c# parallel-processing asynchronous parallel.foreachasync

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

为什么Task.WhenAll的continuations是同步执行的?

Task.WhenAll在 .NET Core 3.0 上运行时,我只是对该方法进行了一个奇怪的观察。我将一个简单的Task.Delay任务作为单个参数传递给Task.WhenAll,并且我预计包装的任务将与原始任务的行为相同。但这种情况并非如此。原始任务的延续是异步执行的(这是可取的),多个Task.WhenAll(task)包装器的延续是一个接一个同步执行的(这是不可取的)。

这是此行为的演示。四个工作任务正在等待同一个Task.Delay任务完成,然后继续进行繁重的计算(由 a 模拟Thread.Sleep)。

var task = Task.Delay(500);
var workers = Enumerable.Range(1, 4).Select(async x =>
{
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}" +
        $" [{Thread.CurrentThread.ManagedThreadId}] Worker{x} before await");

    await task;
    //await Task.WhenAll(task);

    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}" +
        $" [{Thread.CurrentThread.ManagedThreadId}] Worker{x} after await");

    Thread.Sleep(1000); // Simulate some heavy CPU-bound computation
}).ToArray();
Task.WaitAll(workers);
Run Code Online (Sandbox Code Playgroud)

这是输出。四个延续在不同的线程(并行)中按预期运行。

var task = Task.Delay(500);
var workers = Enumerable.Range(1, 4).Select(async x =>
{
    Console.WriteLine($"{DateTime.Now:HH:mm:ss.fff}" +
        $" [{Thread.CurrentThread.ManagedThreadId}] Worker{x} before await"); …
Run Code Online (Sandbox Code Playgroud)

c# continuations task-parallel-library async-await .net-core

18
推荐指数
1
解决办法
957
查看次数

为什么在 C# 中记录类默认是不可变的,但记录结构却不是?

我被教导结构应该几乎总是不可变的,因此记录类与记录结构的这种不寻常行为让我措手不及。

使用记录类...

record class Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Not allowed!
Run Code Online (Sandbox Code Playgroud)

使用记录结构...

record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Fine!
Run Code Online (Sandbox Code Playgroud)

使用只读记录结构...

readonly record struct Person(string FirstName, string LastName);
Person p = new("John", "Smith");
p.FirstName = "Jack" // Now allowed!
Run Code Online (Sandbox Code Playgroud)

为什么readonly记录结构默认是可变的,为什么相同的行为不适用于记录类?

编辑:我想我在这里问的是,为什么语法......很奇怪?

例如,看起来更合乎逻辑:

  • record class-具有值语义的可变引用类型。
  • readonly record class-具有值语义的不可变引用类型。
  • record struct-具有值语义的可变值类型。
  • readonly record struct …

c# record immutability

16
推荐指数
2
解决办法
2911
查看次数

带有异步初始化的 Lazy&lt;Task&lt;T&gt;&gt;

class Laziness
{
    static string cmdText = null;
    static SqlConnection conn = null;

 
    Lazy<Task<Person>> person =
        new Lazy<Task<Person>>(async () =>      
        {
            using (var cmd = new SqlCommand(cmdText, conn))
            using (var reader = await cmd.ExecuteReaderAsync())
            {
                if (await reader.ReadAsync())
                {
                    string firstName = reader["first_name"].ToString();
                    string lastName = reader["last_name"].ToString();
                    return new Person(firstName, lastName);
                }
            }
            throw new Exception("Failed to fetch Person");
        });

    public async Task<Person> FetchPerson()
    {
        return await person.Value;              
    }
}
Run Code Online (Sandbox Code Playgroud)

Riccardo Terrell 于 2018 年 6 月出版的《.NET 中的并发》一书说道: …

c# asynchronous lazy-evaluation async-await

15
推荐指数
2
解决办法
2万
查看次数

我做错了什么或者不能并行提取zip文件?

我创建了这个来测试一个并行提取:

    public static async Task ExtractToDirectoryAsync(this FileInfo file, DirectoryInfo folder)
    {

        ActionBlock<ZipArchiveEntry> block = new ActionBlock<ZipArchiveEntry>((entry) =>
        {
            var path = Path.Combine(folder.FullName, entry.FullName);

            Directory.CreateDirectory(Path.GetDirectoryName(path));
            entry.ExtractToFile(path);

        }, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 2 });

        using (var archive = ZipFile.OpenRead(file.FullName))
        {
            foreach (var entry in archive.Entries.Where(e => e.Name != string.Empty))
            {
                block.Post(entry);
            }
            block.Complete();
            await block.Completion;
        }

    }
Run Code Online (Sandbox Code Playgroud)

以及用于测试的以下单元测试:

    [TestMethod]
    public async Task ExtractTestAsync()
    {
        if (Resources.LocalExtractFolder.Exists)
            Resources.LocalExtractFolder.Delete(true);
        //  Resources.LocalExtractFolder.Create();
        await Resources.WebsiteZip.ExtractToDirectoryAsync(Resources.LocalExtractFolder);
    }
Run Code Online (Sandbox Code Playgroud)

使用MaxDegreeOfParallelism = 1,一切正常,但有两个则没有.

Test Name:  ExtractTestAsync
Test FullName:  Composite.Azure.Tests.ZipFileTests.ExtractTestAsync …
Run Code Online (Sandbox Code Playgroud)

.net c# asynchronous tpl-dataflow

12
推荐指数
1
解决办法
9138
查看次数

何时使用记录结构而不是结构,反之亦然?

我最近发现了C# 中的关键字,并且发现如果我理解正确的话,record它可以用作值类型而不是引用类型。record struct

但是,我很难理解何时确切使用而record struct不仅仅是struct. 据我所知,record struct具有一些结构没有的基本实现(例如==and!=运算符、对 的重写ToString以及其他一些东西),但这就是两者之间的区别吗?如果不是,在决定使用其中一种时需要考虑什么?

从我目前看到的方式来看,最好始终使用record structjust 来利用它已经附带的那些实现。

c# struct c#-9.0 c#-record-type c#-10.0

12
推荐指数
1
解决办法
3626
查看次数

如何使“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
查看次数