小编use*_*225的帖子

只需要'最近'的任务 - 取消/忽略的最佳做法?

我的任务看起来像这样:

var task = Task.Factory.StartNew <object>(LongMethod);
task.ContinueWith(TaskCallback, TaskScheduler.FromCurrentSynchronizationContext());
Run Code Online (Sandbox Code Playgroud)

LongMethod调用一个长期运行的服务,在此期间我不能(或者至少不认为我可以),不断轮询取消令牌以查看它是否已被取消.但是,我有兴趣'取消'或忽略回调方法.

当调用TaskCallback时,我只对'结果'感兴趣,如果它来自最近的任务(让我们假设LongMethod调用的服务保留了顺序,并且还假设用户可以多次单击该按钮,但只有最新的一个是相关的).

我已经通过以下方式修改了我的代码:创建任务后,我将其添加到堆栈的顶部.在TaskCallback中,我检查传递给回调的任务是否是最新的任务(即堆栈顶部的TryPeek).如果不是,我只是忽略了结果.

private ConcurrentStack<Task> _stack = new ConcurrentStack<Task>();

private void OnClick(object sender, ItemClickEventArgs e)
{
    var task = Task.Factory.StartNew < object >( LongMethod);
    task.ContinueWith(TaskCallback, TaskScheduler.FromCurrentSynchronizationContext());
    _stack.Push(task);
 }


private void TaskCallback(Task<object> task)
{
    Task topOfStack;
    if(_stack.TryPeek(out topOfStack)) //not the most recent
    {
        if (task != topOfStack) return;
    }
    //else update UI
}
Run Code Online (Sandbox Code Playgroud)

我很确定这不是"最佳实践"解决方案.但是什么呢?传递和维护取消令牌也不是那么优雅.

c# multithreading task c#-4.0

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

用于枚举的Combobox转换器

我有一个具有类似值的枚举

HomeRun,StolenBase,FirstBase等

我想在组合框中显示这些值,在大写字母之前插入一个空格,因此它将显示为"Home Run","Stolen Base"等.

我已经有了可以为我做格式化的代码,并且我已将该代码添加到IValueConverter实现的'Convert'方法中.

我的问题是,我在哪里需要使用这个转换器(在xaml中),这样不仅下拉列表,而且显示的值,将具有这种格式?我是否还需要实现ConvertBack?

我很清楚为枚举设置'描述'并使用流行的EnumToDescriptionConverter,但我宁愿远离它.

.net c# wpf enums ivalueconverter

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

使用'yield return'观察异步序列

以下示例工作正常:

static IEnumerable<int> GenerateNum(int sequenceLength)
    {
      for(int i = 0; i < sequenceLength; i++)
      {
          yield return i;
      }
    }

static void Main(string[] args)
    {

        //var observ = Observable.Start(() => GenerateNum(1000));
        var observ = GenerateNum(1000).ToObservable();

        observ.Subscribe(
            (x) => Console.WriteLine("test:" + x),
            (Exception ex) => Console.WriteLine("Error received from source: {0}.", ex.Message),
            () => Console.WriteLine("End of sequence.")
            );

        Console.ReadKey();
    }
Run Code Online (Sandbox Code Playgroud)

但是,我真正想要的是使用注释掉的行 - 即我想异步运行'数字生成器',每次它产生一个新值,我希望它输出到控制台.它似乎不起作用 - 如何修改此代码才能工作?

.net c# system.reactive observable

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

继续在主线程上执行任务

如果这是一个简单的问题,请原谅我; 我不能用通用的方式来表达它来搜索答案.

考虑以下代码:

var task = Task.Factory.StartNew(() => Whatever());  
task.ContinueWith(Callback, TaskScheduler.FromCurrentSynchronizationContext())
Run Code Online (Sandbox Code Playgroud)

回调方法执行时究竟如何确定?

它会等到主线程当前完成正在做的事情,还是会在异步调用完成后立即调用?并且这个回调是否会在主线程返回之前执行的任何操作之前完全执行?

c# task c#-4.0

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

实现通用方法

我用一种方法创建了一个接口,能够将一个对象的内容复制到另一个相同类型的对象中(实际功能与问题无关).

public interface IDeepClonable
{
    void DeepClone<T>(T other);
}
Run Code Online (Sandbox Code Playgroud)

我在正确实施方面遇到了麻烦.

我真正想要的是像这样实现它(这是在ClassA中,它实现了IDeepClonable)

public void DeepClone<ClassA>(ClassA other)
{
    this.A = other.A;
}
Run Code Online (Sandbox Code Playgroud)

但是这不起作用,因为编译器不会将"其他"对象识别为ClassA的实例(为什么?)

这也不起作用,因为它给出了'类型参数T的约束必须与(...)接口方法匹配.

public void DeepClone<T>(T other) where T : ClassA
{
    this.A= other.A;
}
Run Code Online (Sandbox Code Playgroud)

我可以通过更改接口而不是通用约束来解决所有问题,但我希望有一个更优雅的解决方案.

我也可以通过将接口转换为通用接口来解决这个问题,但随后迫使我转换为该通用接口.

.net c# generics interface c#-4.0

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

Interlocked.Exchange澄清

我有一些简单(希望)的问题,我一直无法找到答案 -

假设我有多个线程可以访问的对象a,b.

Interlocked.Exchange(ref a, b)
Run Code Online (Sandbox Code Playgroud)

如果'b'不是易变的,这个操作会不会这样处理?即它会从内存中获取此变量的最新值吗?如果是这样,那写入是'原子'吗?据我所知,Interlocked.Exchange的主要目的是使用新写入将原来的'a'值作为原子操作.但我的主要困惑在于'b'实际写入'a'的价值.

我的第二个问题与本文中的引用有关:

http://igoro.com/archive/volatile-keyword-in-c-memory-model-explained/

"一个有趣的观点是,C#中的所有写入都是根据此处和此处记录的内存模型进行的,并且也可能是这样实现的.C#语言的ECMA规范实际上定义了一个较弱的模型,其中写入默认情况下不是易失性的".

这是真的?如果是这样,如果不关心'a'的先前值,是否有Interlocked.Exchange的目的?(与我的第一个例子有关).我没有在StackOverflow上看到任何关于每个写入易失性的文章或评论.但是,我知道写入是原子的.

编辑:如果我的第一个问题的答案是"b"不被视为易失性,而我的第二个问题的答案是写入确实是不稳定的,那么跟进就是,什么时候是联锁的.如果我们不这样做,则有用关心'a'的先前价值?

c# multithreading .net-4.0 interlocked

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

WPF以编程方式根据需要设置字段

我是WPF的新手,但花时间研究WPF验证,还没有看到一个好的方法来进行条件验证.

为了大大简化这种情况,假设我有两个文本框和一个提交按钮.用户在第一个文本框中输入一个字符串.如果用户输入,例如"ABC",则第二个文本框应该是必填字段(我希望背景为浅蓝色,以表示这一点),并且应该禁用提交按钮,直到该文本框为填充.

如何才能做到这一点?有没有简单的方法在运行时添加/删除验证?'DataAnnotations'(http://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.aspx)似乎是一个很好的起点,但我不能用[Required]属性标记一个字段,因为并不总是需要这个领域.基本上,我需要像'如果Field1 ='ABC'那样的东西

谢谢!

c# validation wpf c#-4.0

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

异步加载数据时的反馈

我有一个ComboBox,其ItemsSource绑定到一个ObjectAsProvider,其IsAsynchronous属性设置为true.在加载数据的方法中,我放置了等待10秒,以模拟此数据的长加载时间.

异步加载效果很好 - 整个窗口仍然响应,10秒后我看到填充了ComboBox下拉列表.

我想在10秒的等待时间内提醒用户这个特定的ComboBox正在加载数据.类似于控件背景中的progressBar,仅在某个'isLoading'属性或任何设置为true时启用.有可能做到这一点吗?

谢谢.

c# data-binding wpf asynchronous .net-4.0

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

另一个'是否有这样的设计模式?'

我有两个单独的类,ClassA和ClassB,它们派生自相同的基类,但具有不同的业务逻辑.我需要定义第三个类ClassC,它也派生自相同的基类.这个类将是现有两个类的组合,即,根据某些标准,每当调用ClassC的DoSomething()方法时,我想从ClassA或ClassB调用该方法(这些不是静态方法),基于某些标准.(请注意,对于ClassC的每个实例,确定我是否需要ClassA或ClassB逻辑的标准都可以更改).是否有特定的设计模式可以帮助我开始这个?谢谢.

c# design-patterns

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

Hashcodes是一样的,但是!=返回true?

我被一个看似简单的问题困扰了.我有两个对象,我正在与!=进行比较.

当我运行应用程序时,!= b是真的.当我放置一个断点并执行Watch时,a.GetHashCode()== b.GetHashCode()为true.

这两个(引用类型)对象在不同的​​程序集中定义,但我找不到对!=方法的覆盖(尽管重写了GetHashCode).还有另一种解释吗?两个对象的GetHashCode可能是相同的,但是not-overriden!=会返回true吗?

谢谢.

c# c#-4.0

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

过度使用Interlocked.exchange?

我试图了解Interlocked.Exchange的正确用法,所以我实现了一个带有添加和删除功能的简单排序LinkedList.

如果这不是一个线程安全列表,显然要找到插入点,你会有类似下面的内容来找到插入新节点的正确点.

    public void Insert(int newValue)
    {
        var prev = _header;
        Node curr = _header.Next;

        while(curr != null && curr.value > newValue )
        {
            prev = curr;
            curr = curr.Next;
        }
        var newNode = new Node(newValue, curr);
        prev.Next = newNode;
    }
Run Code Online (Sandbox Code Playgroud)

下面是我对如何为并发列表执行此操作的看法.是否有太多Interlocked.Exchange正在进行?如果没有这个,插入物仍然是线程安全的吗?数百或数千个互锁操作会导致性能下降吗?

    public void InsertAsync(int newValue)
    {
        var prev = _header;
        Node curr = new Node(0, null);
        Interlocked.Exchange(ref curr, _header.Next);

        while (curr != null && curr.value > newValue)
        {
            prev = Interlocked.Exchange(ref curr, curr.Next);
        }
        //need some locking around prev.next …
Run Code Online (Sandbox Code Playgroud)

c# multithreading .net-4.0 lockless

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