TimeCallBack停止的问题

本文探讨了在C#中使用Timer时遇到的问题,特别是当Timer对象被垃圾回收时导致的问题,并提供了一种通过创建后台线程来解决该问题的方法。

以前在学习多线程的时候看过这个东西,玩的时候也没出问题,这次出问题了,不知道为什么。

查了msdn说是调用TimeCallBack的Timer对象是由当前进程的ThreadPool托管,一旦它被GC回收,就完蛋了。

给出的方法是让当前线程停止或者等待Timer的结束

Cnblogs的相关文章:C#多线程学习(五) 多线程的自动管理(定时器)

我的做法是新建一个线程执行,反正最后程序停止它也就被GC了。

void mian()
{            
        Thread t = new Thread(new ThreadStart(BackServer));
            t.IsBackground = true;
            t.Start();     
  }
 void BackServer()
{
            TimerCallback tcb = new TimerCallback(StartRefreshFriends);
            System.Threading.Timer timer = new System.Threading.Timer(tcb, null, 10, 500);
            while (timer != null)
                Thread.Sleep(0);
}
-- Error occurred in anonymous codeblock; filename: ; position: 11926; line: 392 -- MAXScript Rollout Handler Exception: -- Unknown property: "Zoom" in undefined -- MAXScript callstack: -- thread data: threadID:24616 -- ------------------------------------------------------ -- [stack level: 0] -- In gifCombinedRollout.open(); filename: ; position: 11927; line: 392 -- member of: Rollout:gifCombinedRollout -- Locals: -- borderStyleClass: dotNetClass:System.Windows.Forms.BorderStyle -- colorClass: undefined -- sizeModeClass: undefined -- Externals: -- lblFrameInfo: RolloutControl:lblFrameInfo in rollout:gifCombinedRollout : dotNetControl:lblFrameInfo:System.Windows.Forms.Label -- gifCombinedRollout: Rollout:gifCombinedRollout -- owner: Rollout:gifCombinedRollout -- darkGrayCustom: Global:darkGrayCustom : dotNetObject:System.Drawing.Color -- picBoxPlayer: RolloutControl:picBoxPlayer in rollout:gifCombinedRollout : dotNetControl:picBoxPlayer:System.Windows.Forms.PictureBox -- sldFrame: RolloutControl:sldFrame in rollout:gifCombinedRollout : dotNetControl:sldFrame:System.Windows.Forms.TrackBar -- animationRange: SystemGlobal:animationRange : (interval 0f 100f) -- GIFPlayer_TimeCallback: Global:GIFPlayer_TimeCallback : GIFPlayer_TimeCallback() -- originalAnimationRange: Global:originalAnimationRange : (interval 0f 100f) -- Flow: RolloutControl:Flow in rollout:gifCombinedRollout : dotNetControl:Flow:System.Windows.Forms.FlowLayoutPanel -- ------------------------------------------------------ -- [stack level: 1] -- called from top-level true -- Error occurred in anonymous codeblock; filename: ; position: 7646; line: 259 -- MAXScript Rollout Handler Exception: -- Unknown property: "image" in undefined -- MAXScript callstack: -- thread data: threadID:24616 -- ------------------------------------------------------ -- [stack level: 0] -- In cleanupAllResources(); filename: ; position: 7647; line: 259 -- Locals: -- lblFrameInfo: undefined -- lblFileNamePlayer: undefined -- picBoxPlayer: undefined -- sldFrame: undefined -- btnLoadPlayer: undefined -- Externals: -- currentFrame: Global:currentFrame : 1 -- frameCount: Global:frameCount : 0 -- restoreOriginalTimeRange: Global:restoreOriginalTimeRange : restoreOriginalTimeRange() -- gifCombinedRollout: Global:gifCombinedRollout : Rollout:gifCombinedRollout -- owner: undefined -- gifFrames: Global:gifFrames : #() -- imgWidth: Global:imgWidth : 0 -- imgHeight: Global:imgHeight : 0 -- GIFPlayer_TimeCallback: Global:GIFPlayer_TimeCallback : GIFPlayer_TimeCallback() -- gifFileName: Global:gifFileName : "" -- ------------------------------------------------------ -- [stack level: 1] -- called from gifCombinedRollout.close(); filename: ; position: 13333; line: 436 -- member of: Rollout:gifCombinedRollout -- Locals: -- Externals: -- gifCombinedRollout: Rollout:gifCombinedRollout -- owner: Rollout:gifCombinedRollout -- cleanupAllResources: Global:cleanupAllResources : cleanupAllResources() -- ------------------------------------------------------ -- [stack level: 2] -- called from top-level
最新发布
08-27
脚本工具合并我有两个脚本 第一个是批量预览文件夹下的gif, 第二个是加载gif单独适配时间轴的预览工具。 现在我要把这两个工具合并到一起。 第一个脚本工具在左,第二个脚本工具在右。双击第一个脚本工具里面的gif图片实现自动加载到第二个脚本工具里面,这个窗口界面根据第二个脚本里面的gif图片大小等比例缩放。 其他功能不许私自修改 绝对不能修改其他功能。!!!!!!!! 第一个脚本:try(destroyDialog gifViewerRollout) catch() global staticImagesDict = dotNetObject "System.Collections.Hashtable" global resetTimersDict = dotNetObject "System.Collections.Hashtable" global panelHoverStates = dotNetObject "System.Collections.Hashtable" -- 自定义背景颜色(深灰色) global darkGrayCustom = (dotNetClass "System.Drawing.Color").FromArgb 50 50 50 -- 普通边框颜色(灰色) global borderColor = (dotNetClass "System.Drawing.Color").FromArgb 120 120 120 -- 高亮边框颜色(白色) global borderHighlightColor = (dotNetClass "System.Drawing.Color").FromArgb 255 255 255 255 rollout gifViewerRollout "GIF 预览工具" width:620 height:600 ( label lblFolderPath "当前文件夹:" pos:[10,10] width:600 height:25 dotNetControl flow "FlowLayoutPanel" pos:[10,40] width:600 height:520 button btnSelect "选择GIF文件夹" pos:[10,565] width:140 height:30 font:(dotNetObject "System.Drawing.Font" "Segoe UI" 10) on gifViewerRollout open do ( flow.BackColor = darkGrayCustom -- 背景颜色 flow.AutoScroll = true -- 自动滚动,便于查看更多GIF ) fn getFirstFrameBitmap gifPath = ( local origImg = dotNetObject "System.Drawing.Bitmap" gifPath local dimension = dotNetClass "System.Drawing.Imaging.FrameDimension" local frameDim = dimension.Time origImg.SelectActiveFrame frameDim 0 local firstFrame = dotNetObject "System.Drawing.Bitmap" origImg.Width origImg.Height local graphicsClass = dotNetClass "System.Drawing.Graphics" local g = graphicsClass.FromImage firstFrame g.DrawImage origImg 0 0 g.Dispose() origImg.Dispose() firstFrame ) fn resetGifToFirstFrame picBox path = ( try ( local oldImage = picBox.Image if oldImage != undefined and not staticImagesDict.ContainsValue oldImage do ( oldImage.Dispose() ) if staticImagesDict.ContainsKey path do ( picBox.Image = staticImagesDict.Get_Item path ) picBox.Invalidate() picBox.Refresh() ) catch(e) ( format "resetGifToFirstFrame error: %\n" e ) ) fn onMouseEnterHandler sender args = ( local path = sender.Tag as string try ( local panel = sender.Parent if panelHoverStates.ContainsKey panel then panelHoverStates.Set_Item panel true panel.Invalidate() if resetTimersDict.ContainsKey sender do ( local t = resetTimersDict.Get_Item sender t.Enabled = false ) if sender.Image != undefined and not staticImagesDict.ContainsValue sender.Image do ( sender.Image.Dispose() ) sender.Image = (dotNetClass "System.Drawing.Image").FromFile path sender.Refresh() ) catch(e) ( format "onMouseEnterHandler error: %\n" e ) ) fn onResetTimerTick sender args = ( local picBox = sender.Tag if picBox != undefined do ( resetGifToFirstFrame picBox picBox.Tag sender.Enabled = false ) ) fn onMouseLeaveHandler sender args = ( local panel = sender.Parent if panelHoverStates.ContainsKey panel then panelHoverStates.Set_Item panel false panel.Invalidate() local timer = undefined if resetTimersDict.ContainsKey sender then timer = resetTimersDict.Get_Item sender else ( timer = dotNetObject "System.Windows.Forms.Timer" timer.Interval = 100 timer.Tag = sender dotNet.addEventHandler timer "Tick" onResetTimerTick resetTimersDict.Add sender timer ) timer.Enabled = false timer.Enabled = true ) fn panelPaintHandler sender args = ( local g = args.Graphics local isHovered = false if panelHoverStates.ContainsKey sender then isHovered = panelHoverStates.Get_Item sender local penColor = if isHovered then borderHighlightColor else borderColor local pen = dotNetObject "System.Drawing.Pen" penColor 3 local rect = sender.ClientRectangle rect.Width -= 1 rect.Height -= 1 g.DrawRectangle pen rect pen.Dispose() ) fn loadGIFsFromFolder folderPath = ( flow.Controls.Clear() staticImagesDict.Clear() resetTimersDict.Clear() panelHoverStates.Clear() lblFolderPath.text = "当前文件夹:" + folderPath local files = getFiles (folderPath + "\\*.gif") for f in files do ( local panel = dotNetObject "System.Windows.Forms.Panel" panel.Size = dotNetObject "System.Drawing.Size" 130 130 panel.Margin = dotNetObject "System.Windows.Forms.Padding" 5 panel.BorderStyle = (dotNetClass "System.Windows.Forms.BorderStyle").None panel.BackColor = darkGrayCustom -- 背景颜色 -- 初始化Panel悬停状态为false panelHoverStates.Add panel false dotNet.addEventHandler panel "Paint" panelPaintHandler local pb = dotNetObject "System.Windows.Forms.PictureBox" pb.Size = dotNetObject "System.Drawing.Size" 120 120 pb.Location = dotNetObject "System.Drawing.Point" 5 5 pb.SizeMode = pb.SizeMode.Zoom pb.BackColor = darkGrayCustom -- 背景颜色 local staticImg = getFirstFrameBitmap f staticImagesDict.Add f staticImg pb.Image = staticImg pb.Tag = f dotNet.addEventHandler pb "MouseEnter" onMouseEnterHandler dotNet.addEventHandler pb "MouseLeave" onMouseLeaveHandler panel.Controls.Add pb flow.Controls.Add panel ) ) on btnSelect pressed do ( local folder = getSavePath caption:"选择GIF文件夹" if folder != undefined do loadGIFsFromFolder folder ) ) createDialog gifViewerRollout 第二个脚本: try(DestroyDialog ::GIFPlayer)catch() fn GIFPlayer_TimeCallback = ( if ::GIFPlayer != undefined and ::GIFPlayer.gifFrames.count > 0 do ( local currentTime = sliderTime local startFrame = animationRange.start.frame as integer local maxFrame = (currentTime.frame as integer) - startFrame + 1 if maxFrame >= 1 and maxFrame <= ::GIFPlayer.gifFrames.count do ( if maxFrame != ::GIFPlayer.currentFrame do ( ::GIFPlayer.currentFrame = maxFrame ::GIFPlayer.updateDisplay() ) ) ) ) rollout GIFPlayer "GIF预览工具" width:300 height:420 ( local gifFrames = #() local currentFrame = 1 local gifFileName = "" local frameCount = 0 local originalAnimationRange = interval 0 100 local imgWidth = 0 local imgHeight = 0 local minWidth = 300 local maxWidth = 1000 button btnLoad "加载GIF" pos:[10,5] width:280 height:30 label lblFileName "未加载文件" pos:[10,40] width:280 height:20 dotNetControl picBox "System.Windows.Forms.PictureBox" pos:[10,65] width:280 height:280 dotNetControl sldFrame "System.Windows.Forms.TrackBar" pos:[10,350] width:280 height:30 dotNetControl lblFrameInfo "System.Windows.Forms.Label" pos:[10,385] width:280 height:20 fn updateDisplay = ( if gifFrames.count > 0 and currentFrame >= 1 and currentFrame <= gifFrames.count then ( try ( picBox.image = gifFrames[currentFrame] sldFrame.value = currentFrame - 1 -- dotNet滑块从0开始 lblFrameInfo.text = "帧: " + currentFrame as string + " / " + frameCount as string ) catch ( format "显示帧时出错: %\n" (getCurrentException()) ) ) ) fn adjustUIForImage = ( if imgWidth > 0 and imgHeight > 0 do ( -- 计算对话框宽度 (基于图片宽度) local dialogWidth = imgWidth + 40 -- 图片宽度 + 左右边距 dialogWidth = amax #(minWidth, dialogWidth) -- 最小宽度 dialogWidth = amin #(maxWidth, dialogWidth) -- 最大宽度 -- 计算图片框宽度 (对话框宽度 - 左右边距) local picBoxWidth = dialogWidth - 20 -- 计算图片框高度 (保持原始比例) local aspect = imgHeight as float / imgWidth local picBoxHeight = (picBoxWidth * aspect) as integer -- 应用高度限制 local minHeight = 100 local maxHeight = 600 picBoxHeight = amax #(minHeight, picBoxHeight) picBoxHeight = amin #(maxHeight, picBoxHeight) -- 更新控件尺寸和位置 btnLoad.width = picBoxWidth btnLoad.pos = [10,5] lblFileName.width = picBoxWidth lblFileName.pos = [10,40] picBox.width = picBoxWidth picBox.height = picBoxHeight picBox.pos = [10,65] sldFrame.width = picBoxWidth sldFrame.pos = [10, 65 + picBoxHeight + 5] lblFrameInfo.width = picBoxWidth lblFrameInfo.pos = [10, 65 + picBoxHeight + 40] -- 计算总高度 local totalHeight = 65 + picBoxHeight + 65 -- 设置对话框大小 setDialogSize GIFPlayer [dialogWidth, totalHeight] ) ) fn setMaxTimeRange frames = ( local startFrame = animationRange.start local endFrame = startFrame + (frames-1) animationRange = interval startFrame endFrame sliderTime = startFrame redrawViews() ) fn restoreOriginalTimeRange = ( animationRange = originalAnimationRange redrawViews() ) fn cleanupAllResources = ( try(unRegisterTimeCallback GIFPlayer_TimeCallback)catch() if (picBox.image != undefined) do (picBox.image = undefined) for bmp in gifFrames do ( try (if classOf bmp == dotNetObject and isProperty bmp #Dispose do bmp.Dispose()) catch () ) gifFrames = #() lblFileName.text = "未加载文件" currentFrame = 1 frameCount = 0 gifFileName = "" imgWidth = 0 imgHeight = 0 -- 重置UI大小 btnLoad.width = 280 btnLoad.pos = [10,5] lblFileName.width = 280 lblFileName.pos = [10,40] picBox.width = 280 picBox.height = 280 picBox.pos = [10,65] sldFrame.width = 280 sldFrame.pos = [10,350] lblFrameInfo.width = 280 lblFrameInfo.pos = [10,385] setDialogSize GIFPlayer [minWidth, 420] restoreOriginalTimeRange() gc light:true ) on GIFPlayer open do ( -- 设置 PictureBox 属性 local borderStyleClass = dotNetClass "System.Windows.Forms.BorderStyle" picBox.BorderStyle = borderStyleClass.FixedSingle local sizeModeClass = dotNetClass "System.Windows.Forms.PictureBoxSizeMode" picBox.SizeMode = sizeModeClass.Zoom -- 设置 TrackBar 为深灰色 local colorClass = dotNetClass "System.Drawing.Color" sldFrame.BackColor = colorClass.FromArgb 50 50 50 -- 深灰色背景 sldFrame.ForeColor = colorClass.LightGray -- 浅灰色前景 -- 配置 TrackBar sldFrame.AutoSize = false sldFrame.Height = 30 sldFrame.Minimum = 0 sldFrame.Maximum = 99 sldFrame.TickFrequency = 10 sldFrame.SmallChange = 1 sldFrame.LargeChange = 10 sldFrame.Enabled = false -- 配置帧信息标签 lblFrameInfo.Text = "帧: 0 / 0" lblFrameInfo.TextAlign = lblFrameInfo.TextAlign.MiddleCenter lblFrameInfo.ForeColor = colorClass.White lblFrameInfo.BackColor = colorClass.FromArgb 40 40 40 -- 深灰色背景 originalAnimationRange = animationRange registerTimeCallback GIFPlayer_TimeCallback ) on btnLoad pressed do ( local file = getOpenFileName caption:"选择GIF文件" types:"GIF文件(*.gif)|*.gif" if file != undefined then ( cleanupAllResources() gifFileName = file lblFileName.text = filenameFromPath file try ( local netImage = dotNetClass "System.Drawing.Image" local gifImage = netImage.FromFile file imgWidth = gifImage.width imgHeight = gifImage.height -- 调整UI以适应图片比例 adjustUIForImage() local dimension = dotNetClass "System.Drawing.Imaging.FrameDimension" local frameDim = dimension.Time frameCount = gifImage.GetFrameCount frameDim -- 配置滑块 sldFrame.Minimum = 0 sldFrame.Maximum = frameCount - 1 sldFrame.TickFrequency = (frameCount / 10) as integer sldFrame.Enabled = true -- 更新帧信息 lblFrameInfo.Text = "帧: 1 / " + frameCount as string setMaxTimeRange frameCount for i = 0 to frameCount-1 do ( gifImage.SelectActiveFrame frameDim i local frameBmp = dotNetObject "System.Drawing.Bitmap" imgWidth imgHeight local g = (dotNetClass "System.Drawing.Graphics").FromImage frameBmp g.DrawImage gifImage 0 0 imgWidth imgHeight g.Dispose() append gifFrames frameBmp ) if gifFrames.count > 0 then ( currentFrame = 1 updateDisplay() registerTimeCallback GIFPlayer_TimeCallback ) else ( messageBox "未能加载任何帧!" title:"错误" ) gifImage.Dispose() ) catch ( messageBox ("加载GIF时出错:\n" + getCurrentException()) title:"错误" cleanupAllResources() ) ) ) -- dotNet滑块值改变事件处理 on sldFrame ValueChanged args do ( if gifFrames.count > 0 then ( currentFrame = sldFrame.Value + 1 -- dotNet滑块从0开始 updateDisplay() sliderTime = (animationRange.start + (currentFrame-1)) ) ) on GIFPlayer close do (cleanupAllResources()) ) createDialog GIFPlayer
08-27
运行报错 -- Error occurred in anonymous codeblock; filename: ; position: 2947; line: 77 -- MAXScript Rollout Handler Exception: -- Runtime error: callbacks.addScript() unrecognized callback type: #timeChange -- MAXScript callstack: -- thread data: threadID:17536 -- ------------------------------------------------------ -- [stack level: 0] -- In registerTimeCallback(); filename: ; position: 2948; line: 77 -- member of: Rollout:GIFPlayer -- Locals: -- callbackStr: "fn timeCallbackFn = ( try ( local dlg = ::GIFPlayer if isValidObj dlg and dlg.gifFrames.count > 0 do ( -- 获取当前时间轴位置 local currentTime = sliderTime.frame as integer -- 仅当时间变化时更新 if currentTime != dlg.lastSliderTime do ( dlg.lastSliderTime = currentTime dlg.currentFrame = currentTime + 1 -- 确保帧号在范围内 if dlg.currentFrame > dlg.frameCount do dlg.currentFrame = dlg.frameCount if dlg.currentFrame < 1 do dlg.currentFrame = 1 -- 更新显示 dlg.picBox.image = dlg.gifFrames[dlg.currentFrame] dlg.pbFrame.value = (dlg.currentFrame as float / dlg.frameCount * 100) dlg.lblStatus.text = "帧: " + dlg.currentFrame as string + "/" + dlg.frameCount as string ) ) ) catch() )" -- Externals: -- owner: Rollout:GIFPlayer -- callbackID: "GIFPlayer_TimeCallback_88775" -- GIFPlayer: Rollout:GIFPlayer -- ------------------------------------------------------ -- [stack level: 1] -- called from GIFPlayer.open(); filename: ; position: 4554; line: 136 -- member of: Rollout:GIFPlayer -- Locals: -- Externals: -- registerTimeCallback: registerTimeCallback() -- picBox: RolloutControl:picBox in rollout:GIFPlayer : dotNetControl:picBox:System.Windows.Forms.PictureBox -- owner: Rollout:GIFPlayer -- GIFPlayer: Rollout:GIFPlayer -- ------------------------------------------------------ -- [stack level: 2] -- called from top-level
07-16
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值