如何在GUI线程中调用Thread.Execute?

时间:2018-02-06 08:48:55

标签: multithreading delphi lazarus freepascal

有一个 WebView view = (WebView) findViewById(R.id.webView1); view.setWebViewClient(new WebViewClient()); view.getSettings().setJavaScriptEnabled(true); CookieManager.getInstance().setAcceptCookie(true); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { CookieManager.getInstance().setAcceptThirdPartyCookies(view,true); view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } view.getSettings().setUserAgentString("Mozilla/5.0 (iPhone; U; CPU like Mac OS X; en) AppleWebKit/420+ (KHTML, like Gecko) Version/3.0 Mobile/1A543a Safari/419.3"); view.setWebViewClient(new SSLTolerentWebViewClient()); if (Build.VERSION.SDK_INT >= 21) { view.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW); } url = "YOUR URL"; view.loadUrl(url); 后代类,它有自己的TThread方法做一些数学运算。它工作正常,但我正在寻找以下类型的优化。程序的GUI线程和上下文确定要创建,运行和释放这些线程的必要实例的数量。在某些(罕见或用户确定的)情况下,创建一个实例就足够了。

目前我使用以下构造(伪代码):

Execute

因此,代码中有两个地方有我的数学过程,如果应用了一些数学变化,我必须编辑它们。 GUI数学过程与线程中调用的过程稍有不同,所以我不能简单地提取方法并调用它。

我想知道是否有办法创建一个线程实例并在GUI线程中调用它的Execute方法?

2 个答案:

答案 0 :(得分:2)

您可以编写一些严重错误,难以描述的错误代码,以便您安全地拨打TThread的{​​{1}}。但这是荒谬的事情。 Execute()类的重点是它:

  • 在操作系统中启动新线程;
  • 然后在该线程上调用TThread

所以:

  1. 如果您不需要线程,启动您不想使用的线程绝对没有意义
  2. 您需要阻止Execute()对其线程运行进行任何处理。
  3. 然后,您可以从主线程中调用Execute()
  4. 但是,由于您无法保证线程在调用Execute时对 而不是执行任何处理需要多长时间,因此您仍需要等待在破坏Execute()对象之前完成线程
  5.   

    GUI数学过程与线程中调用的过程稍有不同,所以我不能简单地提取方法并调用它。

    这绝对没有意义。

    如果您的两个“数学程序”不同,那么尝试从GUI调用线程实现会改变程序的行为。相反,如果您 可以 重复使用线程实现,那么您肯定 也可以 提取方法! (或者至少是共同的元素。)

    注意

    也就是说,共享可能在TThread中运行的代码时需要谨慎。必须在主线程上运行的任何代码都需要同步或排队。在TThread.Execute()个对象中,您只需调用TThreadSynchronize()方法即可。但是,共享代码不应该放在Queue()对象上,这会让事情变得有点棘手。

    要解决此问题,您可以使用TThread上的Synchronize()Queue()类方法。这允许您在不实例化TThread实例的情况下进行同步。 (注意这些方法可以安全地从主线程调用,因为在这种情况下它们只是直接调用sync方法。)

    以下几行代码应该可以解决问题。

    在合适的对象中实现共享代码。这在概念上是一个 runnable 对象,您可能想要研究它。

    TThread

    如果要从主线程运行共享代码,可以选择以下选项。

    TSharedProcess = class
    private
      { Set this if the process is run from a child thread,
        leave nil if run from main thread. }
      FThread: TThread;
      procedure SyncProc();
    public
      procedure Run();
      property Thread: TThread read FThread write FThread;
    end;
    
    procedure TSharedProcess.Run();
    begin
      ...
      TThread.Synchronize(FThread, SyncProc);
      ...
    end;
    

    要从子线程运行,一个简单的线程包装就足够了。然后,您可以在主线程中创建 runnable 对象,并将其传递给线程包装器。

    begin
      LProc := TSharedProcess.Create(...);
      try
        LProc.Run();
      finally
        LProc.Free;
      end;
    end;
    

    声明

    我没有测试过这段代码,因为我认为做这样的事情没什么好处。用户可以通过强制代码在主线程上运行来获得任何收益。此外,同步代码的范例与异步代码根本不同。尝试使用技术细节来混淆您的“业务代码”,从而降低了可维护性。

    使用风险自负。

答案 1 :(得分:1)

解决此问题的方法是将一个代码提取到一个方法中,该代码需要在工作线程或主线程中执行。然后,您可以从工作线程的Execute方法或主线程代码中调用该代码。