C#线程/异步回调?在这里撕开我的头发

时间:2011-09-16 03:26:05

标签: c# .net asynchronous multithreading

我在线程方面的经验很少。我已阅读消息来源,但大多数利用它的完整项目非常密集,线程只是其中的一小部分,因此难以确定需要什么和不需要什么。

我的项目主要需要为API的更新发出HTTP POST请求,报告(通过回调?)并且很可能放在计时器上,或者可以根据请求多次调用。

我读过的教程只涉及基本内容而没有报告并在新的/新计算的日期上执行更多操作。即使他们这样做,几乎所有人都使用过:

Control.CheckForIllegalCrossThreadCalls = false;

当你经常引用它时,我所读到的内容并不是一个好主意。

所以我想我的问题如下:

  • 我需要各种调度员吗?
  • 是否有更深入/可靠的线程文档和回调参考资料来源?
  • 我应该从两个线程开始,将所有共享变量存储在我可以从main定期检查的第二个线程中,并使用辅助/其他线程更新/更改?

关于学校教育,这不是与学校有关的项目,而是涉及Eve Online API系统的个人项目。 EVEMon的源代码非常紧凑,简化和开发,因此很难区分代码中的线程。如果有人可以指点检查它会有所帮助。

4 个答案:

答案 0 :(得分:1)

Joseph Albahari在线程方面有一套很好的articles,我也发现Jon Skeet的articles非常好。

.net中有很多方法可以使用线程,但要注意,它也很容易出错:)

我个人更喜欢使用reactive extensions,它允许您将典型的异步模式转换为可观察的,并且还可以为您处理ui线程编组。

e.g。

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将观察者编组回UI线程,如果这是您的首选武器,则可以使用特定的调度程序。

如果您想在请求返回之前取消,只需处理从订阅呼叫返回的IDisposable。

Rx需要一些时间来解决问题,但是一旦你这么做就会非常强大。 (我还不了解所有这些)

编辑 - 这是我在winforms应用程序中汇总的一些代码,它使用Rx读取google.com的响应:

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的内容,并确保在订阅上运行的代码位于正确的UI线程上。

只需使用nuget为所有正确的引用安装'Rx-WinForms'包:)

答案 1 :(得分:0)

取决于您所使用的.net框架,在即将发布的c#中,Async会非常容易,

请尝试http://msdn.microsoft.com/en-us/vstudio/async.aspx

答案 2 :(得分:0)

在您的表单上的代码中,您可以做一个简单的

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 
}

答案 3 :(得分:0)

你可以这样做。将定时器控件放到您的表单上,然后在勾选调用中:

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);
        }

这只是将example.org的原始html提取到一个列表框中,但它可以是任何以基本相同的方式更新任何控件的异步查询。