原样,由于线程安全,下面的代码TextProgress
最终不等于TextMax
。如果我在_ViewModel
上锁定`_ViewModel.TextProgress ++',这将纠正此行为。
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
namespace Testing
{
public partial class MainWindow : Window
{
ResultsItemViewModel _ViewModel = new ResultsItemViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = _ViewModel;
_ViewModel.TextMax += 10000;
_ViewModel.TextMax += 10000;
}
private int MAXVAL = 10000;
private void Method1(
Action<int> reportProgress = null)
{
var progress = 0;
for (int i = 0; i < 10000; i++)
{
if (reportProgress != null)
reportProgress.Invoke(++progress);
else
{
_ViewModel.TextProgress++;
}
}
}
private void Method2(
Action<int> reportProgress = null)
{
var progress = 0;
for (int i = 0; i < 10000; i++)
{
if(reportProgress != null)
reportProgress.Invoke(++progress);
else
{
_ViewModel.TextProgress++;
}
}
}
private async Task TextProcessing()
{
await Task.WhenAll(
Task.Run(() => Method1()),
Task.Run(() => Method2()));
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
_ViewModel.TextProgress = 0;
await TextProcessing();
lblResult.Content = _ViewModel.TextProgress + "/" + _ViewModel.TextMax;
}
}
public class ResultsItemViewModel : INotifyPropertyChanged
{
int _textProgress, _textMax;
public int TextProgress
{
get => _textProgress;
set
{
_textProgress = value;
NotifyPropertyChanged();
}
}
public int TextMax
{
get => _textMax;
set
{
_textMax = value;
NotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
}
这有效;
lock (_ViewModel)
{
_ViewModel.TextProgress++;
}
但是,我有很多这些属性需要以这种方式更新,所以我宁愿不必锁定整个_ViewModel
,但同时我宁愿不创建类对于每个属性。理想情况下,我可以做;
lock (_ViewModel.TextProgress)
{
_ViewModel.TextProgress++;
}
但这显然是不可能的。
答案 0 :(得分:1)
如果您想要线程安全,您需要通过例如使用锁来同步对共享资源(TextProgress
)的访问,或者您需要确保仅从以下位置访问共享资源一个线程。你无能为力。
作为使用lock
语句的替代方法,您可以使用Interlocked.Increment方法递增值并将结果存储为原子操作。
但是没有&#34;我确实想要多线程和线程安全,但我不想同步&#34;选择在这里我很害怕。