简体   繁体   English

如何执行多次调用的函数,只执行一次!

[英]How to execute a function called many times, only once !

is there a way to execute a function that is called thousand of times only once ? 有没有办法执行一次只调用一次的函数? I have a function that adds items in a container of sort, and there is code in there, that updates lists and other windows (GUI staff). 我有一个函数,在一个排序容器中添加项目,并有代码,更新列表和其他窗口(GUI人员)。 So, if i have to add a million items (the number of which is impossible to tell, anyone could call the function from anywhere), the GUI update mechanism will be called as many as times... Is there a way to tell appart continuous function execution (and ignore it) from discontinuous ? 所以,如果我必须添加一百万个项目(其数量无法分辨,任何人都可以从任何地方调用该函数),GUI更新机制将被调用多次...有没有办法告诉appart连续函数执行(并忽略它)来自不连续? Is there a safe way to execute the update mechanism only the last time the add-item function is called, within a time interval ? 是否有一种安全的方法在上次调用add-item函数时,在一个时间间隔内执行更新机制?

Thank you. 谢谢。

Roesone, your code is broken. Roesone,你的代码坏了。 It is resisting your attempts to write it because it knows it is wrong. 它拒绝你写它的尝试,因为它知道它是错的。 You can probably find some grungy hack that will emit the behavior you desire -- for now. 你可能会发现一些蹩脚的黑客会发出你想要的行为 - 现在。 But that solution will be a hack; 但那个解决方案将是一个黑客; brittle, prone to errors and difficult to maintain. 脆弱,容易出错,难以维护。 And especially vulnerable to ripple effects. 特别容易受到涟漪效应的影响。 As soon as you make one small change in your code somewhere in something that remotely touches this functionality, the grungy hack will break and you'll be worse off than you are now. 只要你在某个地方对某个远程接触这个功能的东西做了一个小的改动,那个蹩脚的黑客就会破坏,你会比现在更糟糕。

No, the solution here isn't to find a hack that will work. 不,这里的解决方案不是找到一个可行的黑客。 The solution is to fix your code. 解决方案是修复您的代码。 Fundamentally this means writing two functions. 从根本上说,这意味着编写两个函数。 One that inserts the data in to the container, and another completely seperate function that renders that data to the screen. 一个将数据插入容器,另一个完全独立的函数将数据呈现给屏幕。 You can then engineer mechanisms specifically for those methods. 然后,您可以专门为这些方法设计机制。 For instance, you might update the screen ten times per second, while permitting inserts with no restrictions. 例如,您可以每秒更新屏幕十次,同时允许插入没有限制。

Do yourself, your coworkers and the free world a favor and fix your broken code. 做你自己,你的同事和自由世界,并修复你破碎的代码。

你可以放一个static bool ,如果为true,退出函数。

What if you had a way to turn off the "redraw" ( GUI update ) for those situations where you want to add many items? 如果您想要添加许多项目的情况下关闭“重绘”(GUI更新),该怎么办?

// add one item:
window.add_item()

// add many items:
window.set_redraw(false)
window.add_many_items()
window.set_redraw(true)

Then your add_item function simply checks the flag before updating the GUI. 然后你的add_item函数只是在更新GUI之前检查标志。 The simple case of adding one item remains unchanged. 添加一个项目的简单情况保持不变。

可能更好地手动更新触发器。

If you're ok with a timer and using the Win32 API, you could use the SetTimer method to start a timer to trigger in the future each time the function is called. 如果您使用计时器并使用Win32 API,则可以使用SetTimer方法启动计时器,以便在每次调用函数时触发。 The behavior of SetTimer is that if you call it again with the same TimerID before the first call has gone off, then the timer gets reset. SetTimer的行为是,如果在第一次调用关闭之前使用相同的TimerID再次调用它,则计时器将被重置。 So you can call SetTimer each time the function is called and you'd be guaranteed the timer would only trigger "n" milliseconds after the last call. 因此,每次调用函数时都可以调用SetTimer,并且可以保证定时器仅在最后一次调用后“n”毫秒触发。

  UINT_PTR timerID = SetTimer(NULL, someUniqueID, 1000, yourCallback);

Just remember to call KillTimer afterwards to cleanup. 记得随后打电话给KillTimer进行清理。

MSDN for SetTimer SetTimer的MSDN

You need to aggregate the updates to the container over a period of time and then perform your update actions after this time period (easier said than done!). 您需要在一段时间内聚合容器的更新,然后在此时间段之后执行更新操作(说起来容易做起来难!)。 It's important that you are clear which actions are appropriate to aggregate together and which aren't. 重要的是要清楚哪些行为适合聚合在一起,哪些不合适。

The real point is that if you are worried about performance in an area then that is the area that you should concentrate your efforts on eg if you are performing UI update actions at a frequency much higher than your UI display update frequency (or higher than you practically need) then that is the code that should aggregate it's update over the time interval. 真正的一点是,如果您担心某个区域的性能,那么您应该集中精力进行这方面的工作,例如,如果您以远高于UI显示更新频率(或高于您的频率)的频率执行UI更新操作实际需要)然后这是应该在时间间隔内聚合它的更新的代码。

You also need to ensure that you don't leave data structures stale so that the last notification will be acted upon within a timely fashion, even if the next update doesn't happen for a long time. 您还需要确保不要使数据结构过时,以便及时对最后一个通知采取行动,即使下一次更新不会发生很长时间。

The best solution (IMHO) is the one that .NET uses for most of it's controls: 最好的解决方案(恕我直言)是.NET用于大多数控件的解决方案:

Create some sort of a "SuspendLayout" method that sets a boolean and only update the GUI if it is not set. 创建某种“SuspendLayout”方法,该方法设置一个布尔值,只有在未设置的情况下才更新GUI。 Add a "ResumeLayout" that then updates the GUI. 添加“ResumeLayout”,然后更新GUI。

This way if the user of your class only updates a single item he doesn't have to change anything and if he updates several times he can say so and your class doesn't have to worry about it. 这样,如果你班级的用户只更新一个项目,他就不需要改变任何东西,如果他多次更新,他可以这么说,你的班级就不用担心了。

This also allows you to optimize for batch updates if neccessary, ie pre-allocating more space in the list. 这也允许您在必要时优化批量更新,即在列表中预先分配更多空间。 You could also add an override to the SuspendLayout that indicates the number of items that will be added (SuspendLayout(int forNumberOfItems)) so you can initialize the list with the correct amount of space. 您还可以向SuspendLayout添加一个覆盖,指示将添加的项目数(SuspendLayout(int forNumberOfItems)),以便您可以使用正确的空间量初始化列表。

It depends on the framework you use for GUI. 这取决于您用于GUI的框架。

Basically, it boils down to have the following pseudo code : 基本上,它归结为具有以下伪代码:

bool g_isValueModified = false ;
Value g_value ;

void setValue(Value value)
{
   g_value = value ;
   g_isValueModified = true ;
}

void updateValueOnGUI()
{
   if(g_isValueModified)
   {
      g_isValueModified = false ;

      // put here the code to set the value in the GUI widget
   }
}

The method setValue should be called as much as necessary, while the method updateValueOnGUI should be callled, say, once every 10 or 100ms. 方法setValue应该根据需要调用,而方法updateValueOnGUI应该被updateValueOnGUI ,比如每10或100ms updateValueOnGUI一次。

To achieve this asynchronous behaviour, either: 要实现此异步行为,可以:

  • if on raw Win32, use a Win32 timer to call your WinProc 如果在原始Win32上,使用Win32计时器来调用您的WinProc
  • on advanced GUI framework, use a timer 在高级GUI框架上,使用计时器
  • or, on advanced GUI framework, use two separate threads, one for code execution (using the set method) and one for GUI execution (executing the update), making sure g_value and g_isValueModified are written/read in multithread-safe fashion (ie locks, critical sections, etc.). 或者,在高级GUI框架上,使用两个单独的线程,一个用于代码执行(使用set方法),另一个用于GUI执行(执行更新),确保以多线程安全方式(即锁定)写入/读取g_value和g_isValueModified ,关键部分等)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 无论我运行同一个应用程序多少次,应用程序(.exe)中的函数都应该只调用一次 - A Function in an application(.exe) should be called only once regardless of how many times I run the same application 这个函数被调用了多少次? - How many times is this function called? google mock - 怎么说“必须使用某个参数调用一次函数,但可以使用不同的参数调用多次”? - google mock - how to say “function must be called ONCE with a certain parameter but ok to be called many times with different parameters”? 计算一个函数被调用的次数 - Counting how many times a function is called 计算一次 function 被调用多少次 - Count how many times a function is called in a time 这个函数只会调用一次吗? - Will this function only be called once? 如何确保只调用一次函数 - How to make sure a function is only called once 尽管每帧调用一次,但如何只执行一次方法代码 - How to execute method code only once although called every frame 在对象数组中,构造函数被多次调用但是operatror new []只调用一次,为什么? - In the array of objects, constructor is called many times but operatror new[] only once , why? 为什么gprof告诉我从main()仅调用一次的函数被调用102次? - Why does gprof tell me that a function that is called only once from main() is called 102 times?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM