Ввод общих значений (C #)

int[] ids = new[] { 1, 2, 3, 4, 5 };
Parallel.ForEach(ids, i => DoSomething(1, i, blogClient).Wait());

Несмотря на то, что вы выполняете операции параллельно с указанным выше кодом, этот код блокирует каждый поток, в котором выполняется каждая операция. Например, если сетевой вызов занимает 2 секунды, каждый поток висит в течение 2 секунд без каких-либо действий, кроме ожидания.

int[] ids = new[] { 1, 2, 3, 4, 5 };
Task.WaitAll(ids.Select(i => DoSomething(1, i, blogClient)).ToArray());

С другой стороны, приведенный выше код с WaitAll также блокирует нити и ваши потоки не будут свободны обрабатывать любую другую работу до окончания операции.

Рекомендуемый подход

Я предпочел бы WhenAll, который будет выполнять ваши операции асинхронно в Parallel.

public async Task DoWork() {

    int[] ids = new[] { 1, 2, 3, 4, 5 };
    await Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}

Фактически, в приведенном выше case, вам даже не нужно await, вы можете просто прямо вернуться из метода, поскольку у вас нет никаких продолжений:

public Task DoWork() 
{
    int[] ids = new[] { 1, 2, 3, 4, 5 };
    return Task.WhenAll(ids.Select(i => DoSomething(1, i, blogClient)));
}
blockquote>

Чтобы поддержать это, здесь представляет собой подробное сообщение в блоге, в котором рассматриваются все альтернативы и их преимущества / недостатки: Как и где параллельный асинхронный ввод-вывод с веб-интерфейсом ASP.NET

13
задан core 22 March 2009 в 00:14
поделиться

5 ответов

К сожалению, очень трудно убедить компилятор об определенных реализациях T. Один (противный) подход должен бросить для возражения в середине (обратите внимание, что это упакует и распакует типы значения):

int i = (int)(object)this.value;
i++;
this.value = (T)(object)i;

Ужасный, но это работает. В.NET 3.5 у меня есть некоторые лучшие обертки для универсальной арифметики, здесь . Класс Оператора является частью MiscUtil; на самом простом уровне я подозреваю, что AddAlternative работал бы очень хорошо:

this.value = Operator.AddAlternative(this.value, 1);

Это должно вывести неявный < T, int> автоматически, или можно добавить их сами:

this.value = Operator.AddAlternative<T,int>(this.value, 1);

Преимущество : Это предпочтительно для исходного кода, поскольку он на самом деле не заботится об оригинале T - он будет работать на любой тип (даже Ваше собственное), который поддерживает "T + (T, интервал)".

я думаю, что существует также ChangeType, скрывающийся вокруг где-нибудь там...

[редактирование] Collin K и другие делают допустимое замечание об архитектурных последствиях - но быть прагматичным существуют времена, когда T действительно имеет значение так очень..., но я согласился бы с предотвращением этого типа специализации если действительно необходимый. Это сказало (согласно моему комментарию к сообщению Collin), способность выполнить вещи как основная арифметика (инкремент, подразделение Int32, и т.д.) на (например), Matrix< T> [для T в десятичном/плавающем/международном/двойном/и т.д.] часто очень ценно.

24
ответ дан Marc Gravell 22 March 2009 в 00:14
поделиться
  • 1
    @JaredPar: Если набор будет использоваться для управления WPF только для представления, и его запоминающее устройство будет ориентировано на многопотоковое исполнение для нескольких читателей, что является за и против наличия обновлений процесса потока UI индивидуально, по сравнению с наличием набора повышают IObservableCollection " reset" событие на UI распараллеливает, если набор был изменен начиная с последнего было сгенерировано такое событие? Моим пониманием, " набор reset" событие должно заставить любых потребителей набора предполагать, что все объекты, возможно, изменились и действуют соответственно. – supercat 11 February 2013 в 19:01

По-моему, определенный для типа код в универсальном классе является запахом кода. Я осуществил бы рефакторинг его для получения чего-то вроде этого:

public class MyClass<T>
{
 ...
}

public class IntClass : MyClass<int>
{
  public void IncrementMe()
  {
    this.value++;
  }
}
12
ответ дан Collin K 22 March 2009 в 00:14
поделиться
  • 1
    Спасибо. Это было хорошим чтением. Я должен все же реализовать их и проверить, решает ли это мою проблему. – Nuetrino 17 December 2010 в 15:38

Статический контроль типов C# не позволит Вам сделать так, но можно одурачить его с кастингом для возражения. Я не рекомендовал бы делать это, это, вероятно, показывает архитектурную проблему, но так или иначе:

using System;

class Foo<T>
{
  public T value;

  public void Increment()
  {
   if (value is int) value = (T)(object)(((int)(object)value)+1);
  }
}

static class Program
{
    static void Main()
    {
     Foo<int> x = new Foo<int>();
     x.Increment();
     x.Increment();
      Console.WriteLine(x.value); 
    }     
}
3
ответ дан Ilya Ryzhenkov 22 March 2009 в 00:14
поделиться
  • 1
    Спасибо за Ваш ответ. мы в настоящее время - то же событие для сетевого разъединения. Но это событие инициировано только, когда кабель Ethernet удален и не, когда сеть понижается из-за модемного сброса, может быть. В Windows 7 Вы видите значок системного лотка для соединения LAN, которое иногда показывает ограниченную возможность соединения с (опасный символ), это не отображает доступа в Интернет, когда Вы делаете наведение мыши. и когда Интернет восстанавливается с другой стороны, он снова соединяется назад. – Nuetrino 16 December 2010 в 10:12

Я не думаю, что понимаю то, что Вы после. Если Вы требуете, чтобы что-то было определенным типом, то Вы, вероятно, не должны использовать Дженерики. Вы могли, это просто кажется глупым. Это сделает то, что Вы спрашиваете, но я не рекомендую его.

namespace GenericsOne
{
    using System;

class Program
{
    static void Main(string[] args)
    {
        Sample<int> one = new Sample<int>();
        one.AddFive(10);

        // yes, this will fail, it is to show why the approach is generally not a good one.
        Sample<DateTime> two = new Sample<DateTime>();
        two.AddFive(new DateTime());
    }
}

}

namespace GenericsOne
{
    using System;
public class Sample<T>
{
    public int AddFive(T number)
    {
        int junk = 0;

        try
        {
            junk = Convert.ToInt32(number);
        }
        catch (Exception)
        {
            Console.WriteLine("Nope");
        }

        return junk + 5;
    }
}
}
0
ответ дан user25306 22 March 2009 в 00:14
поделиться
  • 1
    Продолжение следует.. Мне было просто любопытно, может ли то конкретное событие быть захвачено. Погугленный много единственные ответы должны проверить с помощью ping-запросов сервер и видеть, соединен ли он или не, и это было бы значительной производительностью наверху для приложения, я исключил это. – Nuetrino 16 December 2010 в 10:14

Поэтому я действительно хочу числовой или операционные ограничения в C#4.

ответ @Marc Gravell является лучшим способом вокруг этого (+1), но это - frustating, как это - проблема для дженериков.

0
ответ дан Community 22 March 2009 в 10:14
поделиться
  • 1
    Этот " ограниченный connectivity" сообщение очень контекстно-зависимо, например, если you' ре позади многих маршрутизаторов. Если Вы действительно хотите знать, являетесь ли Вы " подключенный к internet" необходимо определить то, что Вы подразумеваете под этим. В общем случае лучшее должно соединить до конца точку you' ре, заинтересованное (возможно, в другом потоке с таймером). Обратите внимание также, что ping иногда запрещаются брандмауэрами. При необходимости в HTTP Вам нужно к тестовому порту 80 при необходимости в HTTPS необходимо протестировать 443 и т.д... – Simon Mourier 16 December 2010 в 20:33
Другие вопросы по тегам:

Похожие вопросы: