Unity Xlua AsyncTask Lua异步

--LuaTaskAwaiter
--@module LuaTaskAwaiter
local TaskAwaiter = class("TaskAwaiter")

function TaskAwaiter:ctor()
	self.IsCompleted=false
	self.Packaged = false
	self.actions = {}
end

function TaskAwaiter:GetException()
	return self.exception
end

function TaskAwaiter:GetResult()
	if not self.IsCompleted then
		error("The task is not finished yet")
	end
	if self.exception then
		error(self.exception)
	end
	
	return self.result
end

function TaskAwaiter:SetResult(result,exception,packaged)	
	if exception then
		self.exception = exception
	else
		self.result = result
	end
	
	self.IsCompleted = true
	self.Packaged = packaged
	
	if not self.actions then
		return
	end
	
	for _, v in pairs(self.actions) do
		if v then
			xpcall(v,function(err)
					log:error("%s \n%s",err,debug.traceback())
				end)
		end
	end
end

function TaskAwaiter:OnCompleted(action)
	if not action then
		return
	end
	
	if self.IsCompleted then
		xpcall(action,function(err)
				log:error("%s \n%s",err,debug.traceback())
			end)
		return
	end
	
	table.insert(self.actions,action)
end

---
--AsyncTask
--@module AsyncTask
local M = class("AsyncTask",TaskAwaiter)

function async(action)
	return function(...)
		local task = M()
		if type(action)~='function' then
			task:SetResult(nil,"please enter a function")
			return task
		end
		
		local co = coroutine.create(function(...)
				local results = table.pack(xpcall(action,function(err)
							task:SetResult(nil,err,false)
							log:error("%s \n%s",err,debug.traceback())
						end,...))
				
				local status = results[1]				
				if status then
					table.remove(results,1)
					if #results <=1 then				
						task:SetResult(results[1],nil,false)
					else
						task:SetResult(results,nil,true)
					end
				end	
			end)
		coroutine.resume(co,...)
		return task
	end
end

function await(result)
	assert(result ~= nil,"The result is nil")
	
	local status, awaiter
	if type(result)=='table' and iskindof(result,"TaskAwaiter") then	
		awaiter = result
	elseif type(result) == 'userdata' or type(result) == 'table' then
		status, awaiter = pcall(result.GetAwaiter,result)
		if not status then
			error("The parameter of the await() is error,not found the GetAwaiter() in the "..tostring(result))
		end
	else
		error("The parameter of the await() is error, this is a function, please enter a table or userdata")
	end
	
	if awaiter.IsCompleted then
		local value = awaiter:GetResult()
		if type(value) == 'table' and awaiter.Packaged then
			return table.unpack(value)
		else
			return value
		end
	end
	
	local id = coroutine.running()
	local isYielded= false
	awaiter:OnCompleted(function()			
			if isYielded then
				coroutine.resume(id)
			end
		end)
	
	if not awaiter.IsCompleted then
		isYielded = true
		coroutine.yield()
	end
	
	local value = awaiter:GetResult()
	if type(value) == 'table' and awaiter.Packaged then
		return table.unpack(value)
	else
		return value
	end
end

function try(block)
	local main = block[1]
	local catch = block.catch
	local finally = block.finally
	
	local results = table.pack(pcall(main))
	local status = results[1]
	local e = results[2]
	table.remove(results,1)
	local result = results
	local catched = false
	if (not status) and catch and type(catch)=='function' then
		catched = true
		local results = table.pack(pcall(catch,e))
		if results[1] then
			table.remove(results,1)
			result = results
			e = nil
		else
			e = results[2]
		end		
	end
	
	if finally and 	type(finally)=='function' then
		pcall(finally)
	end	
	
	if status then
		return table.unpack(result)
	elseif catched then
		if not e then
			return table.unpack(result)
		else
			error(e)
		end
	else
		error(e)
	end
end

function M.Run(func,...)
	local action = async(func)
	return action(...)
end

return M


使用示例

-- 异步操作1:定时器
local function timerAsync(seconds)
    return async(function()
        print("timerAsync start")
        await(delay(seconds))
        print("timerAsync end")
        return "timerAsync done"
    end)
end

-- 异步操作2:计时器
local function stopwatchAsync(count)
    return async(function()
        print("stopwatchAsync start")
        for i = 1, count do
            await(delay(1))
            print("stopwatchAsync time: " .. i)
        end
        print("stopwatchAsync end")
        return "stopwatchAsync done"
    end)
end

-- 异步操作3:网络请求
local function requestAsync(url)
    return async(function()
        print("requestAsync start")
        local response = await(http.request(url))
        print("requestAsync end")
        return response
    end)
end

-- 使用 async/await 进行异步编程
local function main()
    print("main start")

    local timerTask = timerAsync(2)
    local stopwatchTask = stopwatchAsync(5)
    local requestTask = requestAsync("https://httpbin.org/get")

    local result1 = await(timerTask)
    print("timerTask result: " .. result1)

    local result2 = await(stopwatchTask)
    print("stopwatchTask result: " .. result2)

    local result3 = await(requestTask)
    print("requestTask result: " .. result3)

    print("main end")
end


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值