C # Threading / Async с обратными вызовами? Рву мои волосы здесь - PullRequest
0 голосов
/ 16 сентября 2011

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

Моему проекту в основном нужно будет отправлять HTTP-запросы POST на обновления для API, отчитываться (через обратный вызов?) И, скорее всего, включать таймер или иметь возможность многократного вызова по запросу.

Прочитанные мною учебные пособия охватывали только базовые вещи, не сообщая о них и выполняя больше операций в новую / вновь рассчитанную дату. Даже когда они это делают, почти все использовали:

Control.CheckForIllegalCrossThreadCalls = false;

Что из того, что я прочитал, не очень хорошая идея, когда вы часто исполняете это цитатой.

Итак, я думаю, мои вопросы следующие:

  • Мне нужен своего рода диспетчер?
  • Существует ли более подробный / надежный источник для документирования потоков и ссылок на обратные вызовы?
  • Должен ли я начать с двух потоков и сохранить все мои общие переменные во втором потоке, с которым я могу регулярно проверять основной, и обновлять / изменять с дополнительным / другим потоком?

Что касается школьного образования, то это не школьный проект, а личный проект с использованием системы Eve Online API. Исходный код EVEMon настолько компактен, оптимизирован и разработан, что довольно трудно различить потоки в его коде. Если бы кто-нибудь мог дать указание на изучение этого, это было бы полезно.

Ответы [ 4 ]

1 голос
/ 16 сентября 2011

Джозеф Албахари имеет хороший набор статей по многопоточности, и я также нашел статей Джона Скита очень хорошими.

В .net есть много способов использовать многопоточность, но будьте осторожны, также очень легко ошибиться:)

Лично я предпочитаю использовать реактивные расширения , которые позволяют преобразовать типичный асинхронный шаблон в наблюдаемый, а также обрабатывают для вас поток пользовательского интерфейса.

, например

var wr = WebRequest.Create("http://someurl");

var o = Observable
    .FromAsyncPattern<WebResponse>(wr.BeginGetResponse, wr.EndGetResponse)()
    .ObserveOnDispatcher()
    .Subscribe(response =>
                    {
                        // do stuff with the response
                    },
                ex =>
                    {
                        //there has been an exception
                    });

Для приложений WPF / Silverlight ObserveOnDispatcher маршаллизирует наблюдателя обратно в поток пользовательского интерфейса, для фигур победы есть специальный планировщик, если это ваше предпочтительное оружие.

Если вы хотите отменить запрос до его возвращения, просто избавьтесь от IDisposable, который возвращается после вызова по подписке.

Rx требуется некоторое время, чтобы привести себя в порядок, но он очень силен, как только вы это сделаете. (Я еще не все понимаю)

Редактировать - вот код, который я набросал в приложении winforms, которое читает ответ от google.com, используя Rx:

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender, EventArgs e)
    {

        var req = WebRequest.Create("http://www.google.com");

        Observable
            .FromAsyncPattern<WebResponse>(req.BeginGetResponse, req.EndGetResponse)()
            .ObserveOn(this)
            .Subscribe(r =>
                            {
                                using (var s = r.GetResponseStream())
                                using (var reader = new StreamReader(s))
                                {
                                    textBox1.Text = reader.ReadToEnd();
                                }
                            },
                        ex =>
                            {
                                textBox1.Text = ex.Message;
                            });
    }
}

Форма имеет текстовое поле и обновит текст ответом или сообщением об исключении ...

Вызов ObserveOn обрабатывает все содержимое Control.Invoke для вас и проверяет, что код, выполняемый по подписке, находится в правильном потоке пользовательского интерфейса.

Просто используйте nuget для установки пакета 'Rx-WinForms' для всех нужных ссылок:)

0 голосов
/ 16 сентября 2011

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

public void AsynchFetchIntoListBox(ListBox listBox)
        {
            var wr = HttpWebRequest.Create("http://example.org");
            IAsyncResult ar = null;
            ar = wr.BeginGetResponse(_ =>
                {
                    var r = wr.EndGetResponse(ar);
                    using (var s = new StreamReader(r.GetResponseStream()))
                    {
                        var result = s.ReadToEnd();
                        listBox.Invoke((Action)(() => 
                            listBox.Items.Add(result)));
                    }
                } , null);
        }

Это просто извлекает необработанный HTML-файл example.org в список, но это может быть любой асинхронный запрос, обновляющий любой элемент управления в основном в том же самом виде.мода.

0 голосов
/ 16 сентября 2011

в вашем коде в форме вы можете просто сделать

private void EventMethod(object sender, EventArgs e)
{
    if (this.InvokeRequired)
    {
        BeginInvoke(new EventHandler(EventMethod), sender, e);
        return;
    }
    //cast your args to the type you know them to be
    //do stuff with e or sender 
}
0 голосов
/ 16 сентября 2011

Зависит от того, на какой платформе .net вы работаете, Async будет очень прост в следующем выпуске c #,

пожалуйста, попробуйте http://msdn.microsoft.com/en-us/vstudio/async.aspx

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...