gpt4 book ai didi

c# - 在 TPL 中安全添加集合

转载 作者:行者123 更新时间:2023-12-02 00:35:36 25 4
gpt4 key购买 nike

在我的 WPF 项目中。我有:

public partial class MainWindow : Window
{
ObservableCollection<Calls> items = new ObservableCollection<Calls>();
public MainWindow()
{
InitializeComponent();
icTodoList.ItemsSource = items;
this.DataContext = new MainViewModel();
}

icTodoList 是一个 ItemsControl,我想为其添加两列。

<DockPanel>
<ItemsControl Height="300" Name="icTodoList" ItemsSource="{Binding Calls}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="60"/>
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<TextBlock Text="{Binding DialingNumber, Mode=OneWay, FallbackValue=' '}" Grid.Column="0"/>
<TextBlock Text="{Binding DialResult, Mode=OneWay, FallbackValue=' '}" Grid.Column="1"/>
</Grid>
</DataTemplate>

</ItemsControl.ItemTemplate>
</ItemsControl></DockPanel>

对于Calls类,我们有

public class Calls : NotifyUIBase
{
private string dialingNumber;
public string DialingNumber
{
get { return dialingNumber; }
set
{
dialingNumber = value;
RaisePropertyChanged();
}
}
public string dialResult;
public string DialResult {
get { return dialResult; }
set
{
dialResult = value;
RaisePropertyChanged();
}
}
}

NotifyUIBase继承自INotifyPropertyChanged,它包含RaisePropertyChanged属性,此处忽略写入以节省空间。

现在,我通过单击“开始”按钮获得了一个生产者-消费者流程。

    private async void Start_Click(object sender, RoutedEventArgs e)
{
var producer = Producer();
var consumer = Consumer();
await Task.WhenAll(producer, consumer);
}

consumer方法中,我们更新ItemsControl。

async Task Consumer()
{
try
{
var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 50
};
var consumerBlock = new ActionBlock<AppointmentReminder>(
remainder =>
{
Calls c = new Calls();
c.DialingNumber = "number..";
c.DialResult = "result...;
items.Add(c);
},
executionDataflowBlockOptions);
bufferBlock.LinkTo(
consumerBlock, new DataflowLinkOptions { PropagateCompletion = true });
await Task.Delay(500);
}

但是我有一个异常(exception):

This type of CollectionView does not support changes to its SourceCollection from a thread different from the Dispatcher thread.

事情发生在线路上:

items.Add(c);

我猜是线程问题,那么如何解决呢?

最佳答案

您已经将一些选项传递给您的 ActionBlock;您可以在那里轻松指定 UI 调度程序:

var executionDataflowBlockOptions = new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(),
};

请注意,它不再并行运行。如果您的操作代码很简单(创建单个对象并设置几个属性),那么这应该足够了。但是,如果对象创建是 CPU 密集型的,您可能希望保持并行性:

var transformOptions = new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = 50
};
var actionOptions = new ExecutionDataflowBlockOptions
{
TaskScheduler = TaskScheduler.FromCurrentSynchronizationContext(),
};
var transformBlock = new TransformBlock<AppointmentReminder, Calls>(reminder =>
{
Calls c = new Calls();
c.DialingNumber = "number..";
c.DialResult = "result...;
return c;
}, transformOptions);
var consumerBlock = new ActionBlock<Calls>(c =>
{
items.Add(c);
}, actionOptions);
var linkOptions = new DataflowLinkOptions { PropagateCompletion = true };
bufferBlock.LinkTo(transformBlock, linkOptions);
transformBlock.LinkTo(consumerBlock, linkOptions);

关于c# - 在 TPL 中安全添加集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26511997/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com