- 浏览: 399475 次
- 性别:
- 来自: 上海
文章分类
- 全部博客 (309)
- xaml C# wpf (0)
- scala java inner clas (1)
- Tools UML Eclipse UML2 (1)
- Timer .NET Framework (1)
- perl (6)
- python function paramter (1)
- Python Docstring (1)
- Python how to compare types (1)
- Python (8)
- java (5)
- C# (76)
- C# WPF (0)
- p4 (0)
- WPF (46)
- .net (6)
- xaml (1)
- javascript (40)
- windows (10)
- scala (4)
- winform (1)
- c++ (48)
- tools (12)
- cmd (1)
- os (0)
- CI (0)
- shell (0)
- C (2)
- haskell (49)
- functional (1)
- tool (1)
- gnu (1)
- linux (1)
- kaskell (0)
- svn (0)
- wcf (3)
- android (1)
最新评论
zz - reprint of Comparing the Timer Classes in the .NET Framework Class Library
- 博客分类:
- Timer .NET Framework
For original article, you might take a look here: http://msdn.microsoft.com/en-us/magazine/cc164015.aspx
Timers
Comparing the Timer Classes in the .NET Framework Class Library
Alex Calvo
This article assumes you're familiar with C#
SUMMARY
Timers often play an important role in both client applications and server-based components (including Windows services). Writing effective timer-driven managed code requires a clear understanding of program flow and the subtleties of the .NET threading model. The .NET Framework Class Library provides three different timer classes: System.Windows.Forms.Timer, System.Timers.Timer, and System.Threading.Timer. Each of these classes has been designed and optimized for use in different situations. This article examines the three timer classes and helps you gain an understanding of how and when each class should be used.
Timer objects in Microsoft® Windows® allow you to control when actions take place. Some of the most common uses of timers are to start a process at a regularly scheduled time, to set intervals between events, and to maintain consistent animation speeds (regardless of processor speed) when working with graphics. In the past, timers have even allowed developers who use Visual Basic® to simulate multitasking.
As you would expect, the Microsoft .NET Framework arms you with the tools you need to tackle each of these scenarios. There are three different timer classes in the .NET Framework Class Library: System.Windows.Forms.Timer, System.Timers.Timer, and System.Threading.Timer. The first two classes appear in the Visual Studio® .NET toolbox window, allowing you to drag and drop both of these timer controls directly onto a Windows Forms designer or a component class designer. If you're not careful, this is where trouble can begin.
The Visual Studio .NET toolbox has a timer control on both the Windows Forms tab and the Components tab (see Figure 1). It is very easy to use the wrong one, or worse yet, to not even realize that they are different. Use the timer control that is located under the Windows Forms tab only if the target is a Windows Forms designer. This control will place an instance of the System.Windows.Forms.Timer class on your form. Like all other controls in the toolbox, you can either let Visual Studio .NET handle the plumbing or you can manually instantiate and initialize the class yourself.
Figure 1 Timer Controls
The timer control that is located on the Components tab can be safely used in any class. This control creates an instance of the System.Timers.Timer class. If you're using the Visual Studio .NET toolbox, you can safely use this timer with either the Windows Forms designer or the component class designer. The component class designer is used by Visual Studio .NET when you're working on a class that derives from System.ComponentModel.Component (as is the case when you're working with Windows services). The System.Threading.Timer class does not appear on the Visual Studio .NET toolbox window. It is somewhat more complicated but provides a higher level of control, as you will see later in this article.
Figure 2 Sample Application
Let's first examine the System.Windows.Forms.Timer and System.Timers.Timer classes. These two classes have a very similar object model. Later I'll explore the more advanced System.Threading.Timer class.Figure 2 shows a screenshot of the sample application that I will be referring to throughout this article. This application will help you gain a clear understanding of each of the timer classes. You can download the complete code from the link at the top of this article and experiment with it.
System.Windows.Forms.Timer
If you're looking for a metronome, you've come to the wrong place. The timer events raised by this timer class are synchronous with respect to the rest of the code in your Windows Forms app. This means that application code that is executing will never be preempted by an instance of this timer class (assuming you don't call Application.DoEvents). Just like the rest of the code in a typical Windows Forms application, any code that resides inside a timer event handler (for this type of timer class) is executed using the application's UI thread. During idle time, the UI thread is also responsible for processing all messages in the application's Windows message queue. This includes Windows API messages as well as the Tick events raised by this timer class. The UI thread processes these messages whenever your application isn't busy doing something else.
If you wrote Visual Basic code prior to Visual Studio .NET, you probably know that in a Windows-based application the only way to allow the UI thread to respond to Windows messages while executing in an event handler is to call the Application.DoEvents method. Just like with Visual Basic, calling Application.DoEvents from the .NET Framework can cause many problems. Application.DoEvents yields control to the UI message pump, allowing all pending events to be processed. This can alter the expected path of execution that I just mentioned. If Application.DoEvents is called from your code, your program flow may be interrupted in order to process the timer events generated by an instance of this class. This can cause unexpected behaviors and make debugging difficult.
How this timer class behaves becomes evident when running the sample application. Clicking the application's Start button, then its Sleep button, and finally the Stop button, will yield the following output:
System.Windows.Forms.Timer Started @ 4:09:28 PM --> Timer Event 1 @ 4:09:29 PM on Thread: UIThread --> Timer Event 2 @ 4:09:30 PM on Thread: UIThread --> Timer Event 3 @ 4:09:31 PM on Thread: UIThread Sleeping for 5000 ms... --> Timer Event 4 @ 4:09:36 PM on Thread: UIThread System.Windows.Forms.Timer Stopped @ 4:09:37 PM
The sample application sets the Interval property of the System.Windows.Forms.Timer class to 1000 milliseconds. As you can see, if the timer event handler had continued to capture timer events while the main UI thread was sleeping (for five seconds), there would have been five timer events displayed as soon as the UI thread woke up again—one for each second the UI thread was sleeping. Instead, the timer remained in a suspended state while the UI thread was sleeping.
Programming the System.Windows.Forms.Timer class couldn't be easier—it has a very simple and intuitive programmatic interface. The Start and Stop methods essentially provide an alternate way of setting the Enabled property (which itself is a thin wrapper around Win32® SetTimer/ KillTimer functions). The Interval property, which I just mentioned, is self-explanatory. Even though you can technically set the Interval property as low as one millisecond, you should be aware that the .NET Framework documentation states that this property is only accurate to approximately 55 milliseconds (provided that the UI thread is available for processing).
Capturing the events raised by an instance of the System.Windows.Forms.Timer class is handled by wiring the Tick event to a standard EventHandler delegate, as shown by the code snippet in the following example:
System.Windows.Forms.Timer tmrWindowsFormsTimer = new System.Windows.Forms.Timer(); tmrWindowsFormsTimer.Interval = 1000; tmrWindowsFormsTimer.Tick += new EventHandler(tmrWindowsFormsTimer_Tick); tmrWindowsFormsTimer.Start(); ••• private void tmrWindowsFormsTimer_Tick(object sender, System.EventArgs e) { //Do something on the UI thread... }
System.Timers.Timer
The .NET Framework documentation refers to the System.Timers.Timer class as a server-based timer that was designed and optimized for use in multithreaded environments. Instances of this timer class can be safely accessed from multiple threads. Unlike the System.Windows.Forms.Timer, the System.Timers.Timer class will, by default, call your timer event handler on a worker thread obtained from the common language runtime (CLR) thread pool. This means that the code inside your Elapsed event handler must conform to a golden rule of Win32 programming: an instance of a control should never be accessed from any thread other than the thread that was used to instantiate it.
The System.Timers.Timer class provides an easy way to deal with this dilemma—it exposes a public SynchronizingObject property. Setting this property to an instance of a Windows Form (or a control on a Windows Form) will ensure that the code in your Elapsed event handler runs on the same thread on which the SynchronizingObject was instantiated.
If you use the Visual Studio .NET toolbox, Visual Studio .NET will automatically set the SynchronizingObject property to the current form instance. At first it may seem as though using this timer class with the SynchronizingObject property makes it functionally equivalent to using the System.Windows.Forms.Timer. For the most part, it is. When the operating system notifies the System.Timers.Timer class that the enabled timer has elapsed, the timer uses the SynchronizingObject.Begin.Invoke method to execute the Elapsed event delegate on the thread on which the SynchronizingObject's underlying handle was created. The event handler will be blocked until the UI thread is able to process it. However, unlike with System.Windows.Forms.Timer, the event will still eventually be raised. As you saw in Figure 2, System.Windows.Forms.Timer will not raise events that occur while the UI thread is unable to process them, whereas System.Timers.Timer will queue them to be processes when the UI thread is available.
Figure 3 shows an example of how to use the SynchronizingObject property. You can use the sample application to analyze this class by selecting the System.Timers.Timer radio button and running through the same sequence of events as you did with the System.Windows.Forms.Timer. Doing so will produce the output shown in Figure 4.
Figure 4 Output
System.Timers.Timer Started @ 5:15:01 PM --> Timer Event 1 @ 5:15:02 PM on Thread: WorkerThread --> Timer Event 2 @ 5:15:03 PM on Thread: WorkerThread --> Timer Event 3 @ 5:15:04 PM on Thread: WorkerThread Sleeping for 5000 ms... --> Timer Event 4 @ 5:15:05 PM on Thread: WorkerThread --> Timer Event 5 @ 5:15:06 PM on Thread: WorkerThread --> Timer Event 6 @ 5:15:07 PM on Thread: WorkerThread --> Timer Event 7 @ 5:15:08 PM on Thread: WorkerThread --> Timer Event 8 @ 5:15:09 PM on Thread: WorkerThread System.Timers.Timer Stopped @ 5:15:10 PM
Figure 3 Using the SynchronizingObject Property
System.Timers.Timer tmrTimersTimer = new System.Timers.Timer(); tmrTimersTimer.Interval = 1000; tmrTimersTimer.Elapsed += new ElapsedEventHandler(tmrTimersTimer_Elapsed); tmrTimersTimer.SynchronizingObject = this; //Synchronize with //the current form... tmrTimersTimer.Start(); ••• private void tmrTimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { // Do something on the UI thread (same thread the form was // created on)... // If we didn't set SynchronizingObject we would be on a // worker thread... }
As you can see, it didn't skip a beat—even when the UI thread was sleeping. An Elapsed event handler was queued to be executed at each event interval. Because the UI thread was sleeping, however, the sample application displays the five timer events (4 through 8) all at once when the UI thread wakes up again and is able to process the handlers.
As I mentioned earlier, the System.Timers.Timer class members are very similar to those of the System.Windows.Forms.Timer class. The biggest difference is that System.Timers.Timer is a wrapper around Win32 waitable timer objects and raises an Elapsed event on a worker thread rather than a Tick event on the UI thread. The Elapsed event must be connected to an event handler that matches the ElapsedEventHandler delegate. The event handler receives an argument of type ElapsedEventArgs.
Above and beyond the standard EventArgs members, the ElapsedEventArgs class exposes a public SignalTime property, which contains the exact time the timer elapsed. Because this class supports access from different threads, it is conceivable that the Stop method may be called on a thread other than the thread that is used for the Elapsed event. This could potentially result in the Elapsed event firing even after the Stop method has been called. You can deal with this by comparing the SignalTime property to the time the Stop method was called.
The System.Timers.Timer class also provides an AutoReset property that determines if the Elapsed event should fire continuously or just once. Keep in mind that resetting the Interval property after the timer has started will reset the current count back to zero. For example, if the interval is set to 5 seconds and 3 seconds have already elapsed before the interval is changed to 10 seconds, the next timer event will be 13 seconds from the last timer event.
System.Threading.Timer
The third timer class comes from the System.Threading namespace. I'd like to say that this is the best of all timer classes, but that would be misleading. For one thing, I was surprised to find that instances of this class are not inherently thread safe, given that it resides in the System.Threading namespace. (Obviously, this doesn't mean it can't be used in a thread-safe manner.) The programmatic interface of this class is not consistent with the other two timer classes and it's also a bit more cumbersome.
Unlike the previous two timer classes that I have just covered, System.Threading.Timer has four overloaded constructors. The following shows what they look like:
The first parameter (callback) requires a TimerCallback delegate that points to a method with the following signature:
public Timer(TimerCallback callback, object state, long dueTime, long period); public Timer(TimerCallback callback, object state, UInt32 dueTime, UInt32 period); public Timer(TimerCallback callback, object state, int dueTime, int period); public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period);
public void TimerCallback(object state);
The second parameter (state) can either be null or an object containing application-specific information. This state object is passed to your timer callback function during each timer event invocation. Keep in mind that the timer callback function is executed on a worker thread, so you'll want to ensure that you have thread-safe access to the state object.
The third parameter (dueTime) allows you to specify when the initial timer event should be fired. You can specify 0 to start the timer immediately or to prevent the timer from automatically starting, you can use the System.Threading.Timeout.Infinite constant.
The fourth parameter (period) allows you to specify the interval (in milliseconds) at which the callback function should be called. Specifying either 0 or Timeout.Infinite for this parameter will disable subsequent timer event invocations.
Once the constructor has been called, you can still alter the dueTime and period settings by using the Change method. This method has the following four overloads:
Here's the code I used in the sample application to start and stop this timer:
public bool Change(int dueTime, int period); public bool Change(uint dueTime, uint period); public bool Change(long dueTime, long period); public bool Change(TimeSpan dueTime, TimeSpan period);
//Initialize the timer to not start automatically... System.Threading.Timer tmrThreadingTimer = new System.Threading.Timer(new TimerCallback(tmrThreadingTimer_TimerCallback), null, System.Threading.Timeout.Infinite, 1000); //Manually start the timer... tmrThreadingTimer.Change(0, 1000); //Manually stop the timer... tmrThreadingTimer.Change(Timeout.Infinite, Timeout.Infinite);
As you might expect, running the sample application with the System.Threading.Timer class selected results in the same output you just saw with the System.Timers.Timer class. Because the TimerCallback function gets called on a worker thread, there are no skipped beats (assuming the availability of worker threads). Figure 5 shows the output from the sample application.
Figure 5 Sample App Output
System.Threading.Timer Started @ 7:17:11 AM --> Timer Event 1 @ 7:17:12 AM on Thread: WorkerThread --> Timer Event 2 @ 7:17:13 AM on Thread: WorkerThread --> Timer Event 3 @ 7:17:14 AM on Thread: WorkerThread Sleeping for 5000 ms... --> Timer Event 4 @ 7:17:15 AM on Thread: WorkerThread --> Timer Event 5 @ 7:17:16 AM on Thread: WorkerThread --> Timer Event 6 @ 7:17:17 AM on Thread: WorkerThread --> Timer Event 7 @ 7:17:18 AM on Thread: WorkerThread --> Timer Event 8 @ 7:17:19 AM on Thread: WorkerThread System.Threading.Timer Stopped @ 7:17:20 AM
Unlike the System.Timers.Timer class, there is no counterpart to the SynchronizingObject property that was offered by the System.Timers.Timer class. Any operations that require access to UI controls should be marshaled using the Control's Invoke or BeginInvoke methods.
Thread-safe Programming with Timers
To maximize code reuse, the sample application calls the same ShowTimerEventFired method from all three different types of timer events. Here are the three timer event handlers:
As you can see, the ShowTimerEventFired method takes the current time and current thread name as arguments. In order to distinguish worker threads from the UI thread, the main entry point for the sample application sets the Name property of the CurrentThread object to "UIThread." The GetThreadName helper method returns either the value of Thread.CurrentThread.Name or "WorkerThread" if the Thread.CurrentThread.IsThreadPoolThread property is true.
private void tmrWindowsFormsTimer_Tick(object sender, System.EventArgs e) { ShowTimerEventFired(DateTime.Now, GetThreadName()); } private void tmrTimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { ShowTimerEventFired(DateTime.Now, GetThreadName()); } private void tmrThreadingTimer_TimerCallback(object state) { ShowTimerEventFired(DateTime.Now, GetThreadName()); }
Because the timer events for System.Timers.Timer and System.Threading.Timer execute on worker threads, it is imperative that any user interface code within these event handlers be marshaled back onto the UI thread for processing. To do this, I created a delegate called ShowTimerEventFiredDelegate:
ShowTimerEventFiredDelegate allows the ShowTimerEventFired method to call itself back on the UI thread.Figure 6 shows the code that makes all this happen.
private delegate void ShowTimerEventFiredDelegate (DateTime eventTime, string threadName);
Figure 6 ShowTimerEventFired
private void ShowTimerEventFired(DateTime eventTime, string threadName) { //InvokeRequired will be true when using //System.Threading.Timer or System.Timers.Timer (without a //SynchronizationObject)... if (lstTimerEvents.InvokeRequired) { //Marshal this call back to the UI thread (via the form //instance)... BeginInvoke(new ShowTimerEventFiredDelegate(ShowTimerEventFired), new object[] {eventTime, threadName}); } else lstTimerEvents.TopIndex = lstTimerEvents.Items.Add( String.Format("—> Timer Event {0} @ {1} on Thread: {2}", ++_tickEventCounter, eventTime.ToLongTimeString(), threadName)); }
It's very easy to determine whether you can safely access a Windows Forms control from the current thread by querying its InvokeRequired property. In this example, if the ListBox's InvokeRequired property is true, the form's BeginInvoke method can be used to call the ShowTimerEventFired method again via ShowTimerEventFiredDelegate. This will ensure that the ListBox Add method executes on the UI thread.
As you can see, there are many issues you need to be aware of when programming with asynchronous timer events. I recommend that you read Ian Griffith's article "Windows Forms: Give Your .NET-based Application a Fast and Responsive UI with Multiple Threads," from the February 2003 issue of MSDN Magazine before using either System.Timers.Timer or System.Threading.Timer.
Dealing with Timer Event Reentrance
There's another subtle issue you'll need to consider when working with asynchronous timer events, such as the events generated by System.Timers.Timer and System.Threading.Timer. The problem has to do with code reentrance. If the code in your timer event handler takes longer to execute than the interval at which the timer is raising events, and you haven't taken the necessary precautions to guard against multithreaded access to your objects and variables, then you could be in for some difficult debugging sessions. Take a look at the following code snippet:
private int tickCounter = 0; private void tmrTimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { System.Threading.Interlocked.Increment(ref tickCounter); Thread.Sleep(5000); MessageBox.Show(tickCounter.ToString()); }
Assuming your timer Interval property is set to 1000 milliseconds, you may be surprised to find out that the first message box that pops up will show a value of 5. This is because during the five seconds that the first timer event was sleeping, the timer kept on generating Elapsed events on different worker threads. Hence, the value of the tickCounter variable was incremented five times before the processing of the first timer event was completed. Notice how I used the Interlocked.Increment method to increment the tickCounter variable in a thread-safe manner. There are other ways to do this, but the Interlocked.Increment method was specifically designed for this kind of operation.
One easy way to solve this type of reentrance problem is to sandwich your timer event handler in a block of code that temporarily disables and then reenables the timer, as shown in the following example:
With this code in place, message boxes will show up every five seconds and, as you would expect, the value of tickCounter will be incremented by one each time. Another option would be to use a synchronization primitive such as Monitor or a mutex to ensure that all future events are queued until the current handler has finished executing.
private void tmrTimersTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { tmrTimersTimer.Enabled = false; System.Threading.Interlocked.Increment(ref tickCounter); Thread.Sleep(5000); MessageBox.Show(tickCounter.ToString()); tmrTimersTimer.Enabled = true; }
Conclusion
For a quick recap of my look at the three timer classes available in the .NET Framework, see the table inFigure 7 which compares these three classes. A point you may want to consider when working with timers is whether your problem can be solved more simply by using the Windows Scheduler (or the AT command for that matter) to run a standard executable periodically.
Figure 7 Timer Classes in the .NET FCL
Timer event runs on what thread? | UI thread | UI or worker thread | Worker thread |
Instances are thread safe? | No | Yes | No |
Familiar/intuitive object model? | Yes | Yes | No |
Requires Windows Forms? | Yes | No | No |
Metronome-quality beat? | No | Yes* | Yes* |
Timer event supports state object? | No | No | Yes |
Initial timer event can be scheduled? | No | No | Yes |
Class supports inheritance? | Yes | Yes | No |
* Depending on the availability of system resources (for example, worker threads) |
For related articles see:
Windows Forms: Give Your .NET-Based Application a Fast and Responsive UI with Multiple Threads
For background information see: Windows Forms: Give Your .NET-Based Application a Fast and Responsive UI with Multiple Threads
Programming the Thread Pool in the .NET Framework: Using Timers
.NET Framework Class Library
相关推荐
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
基于Simulink的语音信号降噪与增强.docx
java资源Java条形码生成库 Barcode4J提取方式是百度网盘分享地址
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
com.bishua666.luxxx1.apk
Nginx配置文件中FastCGI相关参数理解
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
内容概要:本文介绍了由 Google 开发的编程语言 Golang (Go)。Golang 是一种静态类型、编译型且具有垃圾回收功能的并发编程语言,旨在提供简单、可靠和高效的开发体验。它的语法类似于 C 语言,去除了复杂的语法结构,提高了代码可读性和效率。同时,Golang 还提供了卓越的性能、内存管理和跨平台支持,适用于网络应用、分布式系统、云计算等领域。此外,文中提到多个知名公司在其业务中广泛采用了 Go 语言,并定期更新版本以适应不断变化的技术需求。 适合人群:对于对编程感兴趣的技术人员,尤其是希望深入了解并发编程以及寻求高性能后端语言的研发人员。 使用场景及目标:①理解和掌握 Golang 的基本概念及其与其他传统编程语言的区别;②探索 Golang 如何利用 goroutines 和 channels 提供强大的并发编程能力;③了解 Golang 在构建高可用性分布式系统方面的优势。 其他说明:随着 Go 社区的发展壮大和技术的不断创新,学习 Golang 不仅为开发者打开了新的视野,也为未来的项目选型提供了有力支持。
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
功能说明: 系统主要包括主页、个人中心、用户管理、就诊人建档管理、医院介绍管理、科室管理、医生管理、预约挂号管理、用户退号管理、异常提醒管理、留言板、系统管理等功能模块。 环境说明: 开发语言:Java 框架:ssm,mybatis JDK版本:JDK1.8 数据库:mysql 5.7及以上 数据库工具:Navicat11及以上 开发软件:eclipse/idea Maven包:Maven3.3及以上 服务器:tomcat7及以上
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
汉语言文学 4.pdf
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
yolo系列算法目标检测数据集,包含标签,可以直接训练模型和验证测试,数据集已经划分好,包含数据集配置文件data.yaml,适用yolov5,yolov8,yolov9,yolov7,yolov10,yolo11算法; 包含两种标签格:yolo格式(txt文件)和voc格式(xml文件),分别保存在两个文件夹中; yolo格式:<class> <x_center> <y_center> <width> <height>, 其中: <class> 是目标的类别索引(从0开始)。 <x_center> 和 <y_center> 是目标框中心点的x和y坐标,这些坐标是相对于图像宽度和高度的比例值,范围在0到1之间。 <width> 和 <height> 是目标框的宽度和高度,也是相对于图像宽度和高度的比例值
中国城镇住户微观数据(1986-2015)-最新全集.zip
python whl离线安装包 pip安装失败可以尝试使用whl离线安装包安装 第一步 下载whl文件,注意需要与python版本配套 python版本号、32位64位、arm或amd64均有区别 第二步 使用pip install XXXXX.whl 命令安装,如果whl路径不在cmd窗口当前目录下,需要带上路径 WHL文件是以Wheel格式保存的Python安装包, Wheel是Python发行版的标准内置包格式。 在本质上是一个压缩包,WHL文件中包含了Python安装的py文件和元数据,以及经过编译的pyd文件, 这样就使得它可以在不具备编译环境的条件下,安装适合自己python版本的库文件。 如果要查看WHL文件的内容,可以把.whl后缀名改成.zip,使用解压软件(如WinRAR、WinZIP)解压打开即可查看。 为什么会用到whl文件来安装python库文件呢? 在python的使用过程中,我们免不了要经常通过pip来安装自己所需要的包, 大部分的包基本都能正常安装,但是总会遇到有那么一些包因为各种各样的问题导致安装不了的。 这时我们就可以通过尝试去Python安装包大全中(whl包下载)下载whl包来安装解决问题。
中国数字经济发展与基础设施指标(2011-2020)-最新数据.zip
中国数字经济数据(全国-省-市-县-乡)-最新.zip