UE4_AsyncTask应用笔记

在开发过程中如果把所有的逻辑都放到GameThread里,难免会卡顿。因此这时候,往往会用到多线程。UE4提供的多线程解决方案有三种。这里我们着重说一下AsyncTask的应用。

一般来说,用AsyncTask都是一些业务逻辑不复杂的交给它来处理。因为省去了new Thread的开销。
AsyncTask 下边又有几种不同的Task类型,这里说的是FNonAbandonableTask 和 FAutoDeleteAsyncTask。

对于FAutoDeleteAsyncTask,在任务结束的时候,它会自动清理。我们并不需要手动清理,但是造成的问题就是,如果我们在new FAutoDeleAsyncTask 传入了外部的类实例,在外部类实例销毁时,new 出来的Task 可能并没有运行结束,这里就会报空指针的问题,造成程序的中断和崩溃。

因此,当我们需要外部传入类实例的时候,可以使用FAutoDeleteAsyncTask,因为它下边提供了可以用来判断任务是否已经结束了的API接口。
如下:

/** Returns true if the work and TASK has completed, false while it's still in progress. 
	 * prior to returning true, it synchronizes so the task can be destroyed or reused
	 */
	bool IsDone()
	{
		if (!IsWorkDone())
		{
			return false;
		}
		SyncCompletion();
		return true;
	}

	/** Returns true if the work has completed, false while it's still in progress. 
	 * This does not block and if true, you can use the results.
	 * But you can't destroy or reuse the task without IsDone() being true or EnsureCompletion()
	*/
	bool IsWorkDone() const
	{
		if (WorkNotFinishedCounter.GetValue())
		{
			return false;
		}
		return true;
	}

	/** Returns true if the work has not been started or has been completed. 
	 * NOT to be used for synchronization, but great for check()'s 
	 */
	bool IsIdle() const
	{
		return WorkNotFinishedCounter.GetValue() == 0 && QueuedPool == 0;
	}
	/** 
	* Wait until the job is complete
	* @param bDoWorkOnThisThreadIfNotStarted if true and the work has not been started, retract the async task and do it now on this thread
	**/
	void EnsureCompletion(bool bDoWorkOnThisThreadIfNotStarted = true)
	{
		bool DoSyncCompletion = true;
		if (bDoWorkOnThisThreadIfNotStarted)
		{
			if (QueuedPool)
			{
				if (QueuedPool->RetractQueuedWork(this))
				{
					// we got the job back, so do the work now and no need to synchronize
					DoSyncCompletion = false;
					DoWork(); 
					FinishThreadedWork();
					QueuedPool = 0;
				}
			}
			else if (WorkNotFinishedCounter.GetValue())  // in the synchronous case, if we haven't done it yet, do it now
			{
				DoWork(); 
			}
		}
		if (DoSyncCompletion)
		{
			SyncCompletion();
		}
		CheckIdle(); // Must have had bDoWorkOnThisThreadIfNotStarted == false and needed it to be true for a synchronous job
	}

因此,可以在析构一个类时,等待所有的Task完成,再执行析构和退出,就不会再报异常错误。

// 数组
TArray<FAsyncTask<DoKafkaTask>*> TaskArr;

FAsyncTask<DoKafkaTask>* task = new FAsyncTask<DoKafkaTask>(this, request);
TaskArr.Add(task);
task->StartBackgroundTask();

AKafkaMsgManager::~AKafkaMsgManager()
{
	// 确保所有的异步任务被执行完毕 不然会在异步任务中报空指针的错误
	for (auto local_task : TaskArr)
	{
		if (!local_task->IsDone())
		{
			local_task->EnsureCompletion();
		}
	}
}


其他另外关于多线程和异步的文章,请参阅。
UE4_异步_数据处理(Json)
UE4_多线程、异步执行任务

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值