等待 RunOnUIThread 完成并继续执行剩余的任务
Wait for RunOnUIThread to finish and continue executing the rest of the task
我正在通过 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);
}
首先你应该避免创建新的Threads
。
在你的情况下,你必须使用 ThreadPool.QueueUserWorkItem
来排队 CPU 绑定操作。
然后您可以使用 ManualResetEventSlim
或 TaskCompletionSource
来同步 UI thread
和工作线程。
示例:
// 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();
}
}
您可以将 Monitor.Wait
和 Monitor.Pulse
与共享 myLock
对象一起使用以等待 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);
对于那些对 async
/await
解决方案感兴趣的人,有 Stephen Cleary 的 AsyncManualResetEvent
,例如:
var mre = new AsyncManualResetEvent();
this.context.RunOnUiThread(() =>
{
// Do awesome UI stuff
mre.Set();
});
await mre.WaitAsync();
我正在通过 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);
}
首先你应该避免创建新的Threads
。
在你的情况下,你必须使用 ThreadPool.QueueUserWorkItem
来排队 CPU 绑定操作。
然后您可以使用 ManualResetEventSlim
或 TaskCompletionSource
来同步 UI thread
和工作线程。
示例:
// 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();
}
}
您可以将 Monitor.Wait
和 Monitor.Pulse
与共享 myLock
对象一起使用以等待 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);
对于那些对 async
/await
解决方案感兴趣的人,有 Stephen Cleary 的 AsyncManualResetEvent
,例如:
var mre = new AsyncManualResetEvent();
this.context.RunOnUiThread(() =>
{
// Do awesome UI stuff
mre.Set();
});
await mre.WaitAsync();