等待RunOnUIThread执行完毕,然后继续执行剩余的任务

4
我正在通过 C#(Xamarin.Visual Studio)为Android开发应用程序,问题是我有一些在其他线程中运行的任务,当它应该更新布局时,它应该调用 Activity.RunOnUIThread , 一切都正常工作,但该线程不等待此方法完成即继续执行其余部分而不等待。
问题是:如何等待 RunOnUIThread 完成后再继续执行任务的其余命令?
public void start(int threadCounter)
    {
        for (int i = 0; i < threadCounter; i++)
        {

            Thread thread1 = new Thread(new ThreadStart(RunScanTcp));
            thread1.Start();

        }

    }
    public void RunScanTcp()
    {

        int port;

        //while there are more ports to scan 
        while ((port = portList.NextPort()) != -1)
        {
            count = port;

            Thread.Sleep(1000); //lets be a good citizen to the cpu

            Console.WriteLine("Current Port Count : " + count.ToString());

            try
            {

                Connect(host, port, tcpTimeout);

            }
            catch
            {
                continue;
            }

            Activity.RunOnUiThread(() =>
            {
                mdata.Add(new data() { titulli = "Port : " + port, sekuenca = "Sequence : ", ttl = "Connection Sucessfull !", madhesia = "", koha = "Time : " });
                mAdapter.NotifyItemInserted(mdata.Count() - 1);
                if (ndaluar == false)
                {
                    mRecyclerView.ScrollToPosition(mdata.Count() - 1);
                }
            }); // in that point i want to wait this to finish and than continue below...
            Console.WriteLine("TCP Port {0} is open ", port);

        }

请查看我的答案以获取一个可行的示例。 - jzeferino
3个回答

4

首先,您应避免创建新的 Threads

在您的情况下,您必须使用 ThreadPool.QueueUserWorkItem 将 CPU 绑定操作入队。

然后,您可以使用 ManualResetEventSlimTaskCompletionSource 同步 UI 线程 和工作线程。

示例:

// mre is used to block and release threads manually. It is
// created in the unsignaled state.

ManualResetEventSlim mre = new ManualResetEventSlim(false);

RunOnUiThread(() =>
{            
    // Update UI here.
    // Release Manual reset event.

    mre.Set();
});

// Wait until UI operations end.
mre.Wait();

在您的具体情况下:
for (int i = 0; i < threadCounter; i++)
{
    ThreadPool.QueueUserWorkItem(RunScanTcp);
}

private void RunScanTcp(object stateInfo) 
{
    // Do CPU bound operation here.
    var a = 100;
    while (--a != 0)
    {
        // mre is used to block and release threads manually. It is
        // created in the unsignaled state.
        ManualResetEventSlim mre = new ManualResetEventSlim(false);

        Activity.RunOnUiThread(() =>
        {
            // Update UI here.

            // Release Manual reset event.
            mre.Set();
        });

        // Wait until UI operation ends.
        mre.WaitOne();
    }
}

如果您更喜欢使用TaskCompletionSource,您可以使用 另一种方法

private async void RunScanTcp(object stateInfo)
{
    // Do CPU bound operation here.
    var a = 100;
    while (--a != 0)
    {
        // using TaskCompletionSource
        var tcs = new TaskCompletionSource<bool>();

        RunOnUiThread(() =>
        {
            // Update UI here.

            // Set result
            tcs.TrySetResult(true);
        });

        // Wait until UI operationds.
        tcs.Task.Wait();
    }
}

那么,使用ThreadPool.QueueUserWorkItem比创建新线程更好吗?我会尝试这个解决方案,谢谢。 - EAK TEAM
是的,更好的选择是因为ThreadPool由Runtime进行管理。我可以用我给你的代码替换你的代码,它可以直接运行,我已经在我的机器上测试过了。 - jzeferino

1
你可以使用共享的myLock对象,结合Monitor.WaitMonitor.Pulse方法来等待UI执行。
Activity.RunOnUiThread(() =>
{
    mdata.Add(new data() { titulli = "Port : " + port, sekuenca = "Sequence : ", ttl = "Connection Sucessfull !", madhesia = "", koha = "Time : " });
    mAdapter.NotifyItemInserted(mdata.Count() - 1);
    if (ndaluar == false)
    {
        mRecyclerView.ScrollToPosition(mdata.Count() - 1);
    }
    lock(myLock) Monitor.Pulse(myLock)
});
lock(myLock) Monitor.Wait(myLock)
Console.WriteLine("TCP Port {0} is open ", port);

myLock 可以是正确范围内的任何对象。 - tynn

0

对于那些对async/await解决方案感兴趣的人,可以使用Stephen Cleary的AsyncManualResetEvent,例如:

var mre = new AsyncManualResetEvent();
this.context.RunOnUiThread(() =>
{
    // Do awesome UI stuff
    mre.Set();
});
await mre.WaitAsync();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接