await async with Iron Python

2019-08-17 06:49发布

For now I was using Parallel methods to check urls for 200 status code, but this was slow method. Now I'm trying to move my code to await/async methods but it doesn't working

        private async void button1_Click(object sender, EventArgs e)
        {
            DateTime start = DateTime.Now;

            var timerPostingSpeed = new Timer(state =>
            {
                TimeSpan elapsed = DateTime.Now - start;
                string postingSpeed = string.Format("{0:0}",
                                                   finishedUrls * 60 / (int)elapsed.TotalSeconds);
                UpdatingLabel(label1, postingSpeed);
            }, null, 5000, 10000);


            IEnumerable<string> urls = File.ReadLines("urls.txt");

            var engine = Python.CreateEngine();

            var scriptSource =
                   engine.CreateScriptSourceFromString(@"
                        if Open(__URL).Result:
                            print 1
                        ");

            await urls.ForEachAsync(20, async line =>
            {
                try
                {

                    var adderEngine = new SpeedEngine();
                  //  int zz = await adderEngine.Open(line);
                   // return;
                        ScriptScope scope = engine.CreateScope();

                        scope.SetVariable("__URL", line);

                        scope.SetVariable("Open",
                            new Func<string, Task<int>>(adderEngine.Open));
                    try
                    {
                        await scriptSource.Execute(scope);
                    }
                    catch (UnboundNameException une)
                    {
                        MessageBox.Show(une.Message,
                            msg.
                                MySeoBoxForm_startPostingToolStripButton_Click_Unbound_Name_Error,
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (SyntaxErrorException see)
                    {
                        MessageBox.Show(
                            string.Format("{0}\nLine: {1}\nCode: {2}",
                                see.Message,
                                see.Line, see.GetCodeLine()),
                            msg.
                                MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (MissingMemberException mme)
                    {
                        MessageBox.Show(mme.Message, "Missing Member",
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (ArgumentTypeException ate)
                    {
                        MessageBox.Show(string.Format("{0}", ate.Message),
                            msg.
                                MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
                            MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    catch (SystemExitException)
                    {

                    }
                    catch (Exception exc)
                {
                     MessageBox.Show(string.Format("{0}", exc.Message),
                       msg.
                           MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
                       MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                    finally
                    {

                     MessageBox.Show(string.Format("{0}","OK"),
                       msg.
                           MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
                       MessageBoxButtons.OK, MessageBoxIcon.Error);

                    }

                }
                catch (Exception exc)
                {
                     MessageBox.Show(string.Format("{0}", exc.Message),
                       msg.
                           MySeoBoxForm_startPostingToolStripButton_Click_Syntax_Error,
                       MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                finally
                {
                    Interlocked.Increment(ref finishedUrls);
                    numericUpDown1.Invoke(new MethodInvoker(delegate
                    {
                        numericUpDown1.Value++;
                    }));
                }

            });
            timerPostingSpeed.Dispose();
        }

    }

   public async Task<int> Open(string siteUrl)
        {
                Uri newUri;
                if (!Uri.TryCreate(siteUrl, UriKind.Absolute, out newUri)) return 0;
                _uri = _openUri = newUri;
                _req = new HttpRequestMessage(HttpMethod.Get, _uri);

                _response = await _httpClient.SendAsync(_req);

                if (_response == null || !_response.IsSuccessStatusCode)
                {
                  return 0;
                }


                return 1;
        }

I need to use Iron Python - without it (when I uncomment await adderEngine.Open(line); return;) everything works ok. But with Iron Python my app stopped at *_response = await _httpClient.SendAsync(_req);* without errors. Also I noticed when I replace

await urls.ForEachAsync(20, async line =>

with:

await urls.ForEachAsync(1, async line =>

it's working

ForEachAsync: http://blogs.msdn.com/b/pfxteam/archive/2012/03/05/10278165.aspx

Any help?

1条回答
成全新的幸福
2楼-- · 2019-08-17 07:32

If your Python code is calling Task.Result, and you're on a UI thread (as appears to be the case), you can cause a deadlock (I explain this fully on my blog). In short, the async method (Open) is trying to resume execution on the UI thread, but the UI thread is blocked by calling Result.

AFAIK, Python does not have async/await support, but you should be able to use ContinueWith (meh) or write some kind of bridge between Task and Twisted's Deferred (much cooler).

查看更多
登录 后发表回答